Java多线程学习中遇到的一个有趣的问题

今天随便写了一个线程之间相互调度的程序,代码如下:

class First extends Thread
{
	public First()
	{
		start();
	}

	synchronized public void run()
	{
		try
		{
			wait();
		}
		catch(InterruptedException e)
		{
			e.printStackTrace();
		}
		try
		{
			sleep(2000);
		}
		catch(InterruptedException e)
		{
			e.printStackTrace();
		}
		System.out.println("hello world~");
	}
}

class Second extends Thread
{
	First first;
	public Second(First first)
	{
		this.first = first;
		start();
	}

	synchronized public void run()
	{
		try
		{
			wait();
		}
		catch (InterruptedException e1)
		{
			e1.printStackTrace();
		}
		synchronized( first )
		{
			try
			{
				sleep(2000);
				System.out.println("I'm faster than first~");
			}
			catch(InterruptedException e)
			{
				e.printStackTrace();
			}
			first.notifyAll();
		}
	}
}

public class Main
{
	public static void main(String[] args) throws InterruptedException
	{
		First first = new First();
		Second second = new Second(first);
		synchronized( second )
		{
			System.out.println("I'm faster than second~");
			second.notifyAll();
		}
	}
}

本以为输出会很顺畅,但是出现的问题是,只输出了一行:I‘m faster than second~

程序就一直处于无响应状态,纠结了好久终于想明白是这么一回事:在main函数中,对second.notifyAll()的调用早于second中的wait()调用(因为是多线程并行,故函数响应时间与代码先后顺序无关),这样先唤醒了second,紧接着second才开始wait,因此就处于无响应状态。

改进方法:只要在second.notifyAll()调用之前空出一点时间先让second的wait调用开始即可,事实上,这段时间如此之短以至于在我电脑上只需要在之前加一行输出语句即可。为了保险起见,还是多加了个sleep,改进后代码如下:

class First extends Thread
{
	public First()
	{
		start();
	}

	synchronized public void run()
	{
		try
		{
			wait();
		}
		catch(InterruptedException e)
		{
			e.printStackTrace();
		}
		try
		{
			sleep(2000);
		}
		catch(InterruptedException e)
		{
			e.printStackTrace();
		}
		System.out.println("hello world~");
	}
}

class Second extends Thread
{
	First first;
	public Second(First first)
	{
		this.first = first;
		start();
	}

	synchronized public void run()
	{
		try
		{
			wait();
		}
		catch (InterruptedException e1)
		{
			e1.printStackTrace();
		}
		synchronized( first )
		{
			try
			{
				sleep(2000);
				System.out.println("I'm faster than first~");
			}
			catch(InterruptedException e)
			{
				e.printStackTrace();
			}
			first.notifyAll();
		}
	}
}

public class Main
{
	public static void main(String[] args) throws InterruptedException
	{
		First first = new First();
		Second second = new Second(first);
		System.out.println("wating for all threads prepared~");
		Thread.sleep(2000);
		synchronized( second )
		{
			System.out.println("I'm faster than second~");
			second.notifyAll();
		}
	}
}

输出结果:

wating for all threads prepared~

I‘m faster than second~

I‘m faster than first~

hello world~

时间: 2024-10-12 19:21:36

Java多线程学习中遇到的一个有趣的问题的相关文章

java多线程问题中死锁的一个实现

1.直接上代码: class LockDemo{ public static final Object A_LOCK=new Object(); public static final Object B_LOCK=new Object(); } public class ThreadLockDemo implements Runnable{ public boolean flag; public ThreadLockDemo(boolean flag) { this.flag=flag; } p

java多线程学习(3)

1)竞争条件 在实际的多线程应用中,通常会有两个或多个线程需要对共同的对象进行共享访问,如果两个线程访问相同的对象,而且每一个都调用了一个会改变对象状态的方法, 那么,线程就会相互倾轧.根据各个线程访问数据的不同顺序,可能会产生腐蚀现象.这种情况通常称为竞争条件. 2)同步 为了多个线程对共享数据的腐蚀,就需要对数据的存取实现同步:常用的同步方法有3种: 1.Reenlock 用Reenlock保护代码块的基本机构如下: 1 Lock myLock=new ReenLock; 2 3 myLoc

java多线程学习(2)

1)Callable和Future Runnable封装一个异步运行的任务:可以当成一个没有任何参数和返回值的异步方法,Callable和 Runnable类似,但是它有返回值和参数. Callable接口是一个参数化的类型,只有一个方法call. 1 public interface Callable<V> 2 3 { 4 5 V call()throws Exception; 6 7 } 类型参数v是指返回值的类型,例如Callable<Integer>代表最终返回一个Inte

java多线程学习--java.util.concurrent

CountDownLatch,api 文档:http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes. 假设我们要打印1-100,最

黑马程序员之Java多线程学习

android培训  java培训 期待与您交流! 这一篇文章主要关于java多线程,主要还是以例子来驱动的.因为讲解多线程的书籍和文章已经很多了,所以我也不好意思多说,呵呵.大家可以去参考一些那些书籍.我这个文章主要关于实际的一些问题.同时也算是我以后复习的资料吧,.呵呵大家多多指教. 同时希望多结交一些技术上的朋友.谢谢. -------------------------------------------------------------------------------------

[转]Java多线程学习(总结很详细!!!)

Java多线程学习(总结很详细!!!) 此文只能说是java多线程的一个入门,其实Java里头线程完全可以写一本书了,但是如果最基本的你都学掌握好,又怎么能更上一个台阶呢? 本文主要讲java中多线程的使用方法.线程同步.线程数据传递.线程状态及相应的线程函数用法.概述等.首先让我们来了解下在操作系统中进程和线程的区别: 进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1--n个线程.(进程是资源分配的最小单位) 线程:同一类线程共享代码和数据空间,

java多线程学习(1)

1)多线程与多进程的区别 多线程和多进程有什么区别呢?本质的区别在于每个进程有它自己的变量的完备集,线程则共享相同的数据. 对程序来说,共享的变量会使得线程之间的通信比进程间的通信更加有效和简单:同时,线程相对于进程来说,更加的“轻量级”, 线程的创建和销毁要比 进程的 开销要小的多. 2)多线程程序的构造 多线程的构造通常有两种方法, 第一种方法是,构建一个Thread的子类,并重写它的run()方法: 1 class MyThread extends Thread 2 { 3 4 publi

Java多线程编程中Future模式的详解&lt;转&gt;

Java多线程编程中,常用的多线程设计模式包括:Future模式.Master-Worker模式.Guarded Suspeionsion模式.不变模式和生产者-消费者模式等.这篇文章主要讲述Future模式,关于其他多线程设计模式的地址如下:关于其他多线程设计模式的地址如下:关于Master-Worker模式的详解: Java多线程编程中Master-Worker模式的详解关于Guarded Suspeionsion模式的详解: Java多线程编程中Guarded Suspeionsion模式

Java多线程学习幸运飞艇采集器修复

package javastudy01; class MyThread extends Thread {//重写Run方法public void run(){//1.获取当前线程的名字System.out.println(this.getName()+"我是一个线程."); } public static void main(String[] args) {Java多线程学习幸运飞艇采集器修复,需要请搜索[大神源码论坛]dsluntan.com 客服企娥3393756370 V信170