线程间通信:多个线程在处理同一资源,但是线程任务却不同
如图:有两辆车,一辆车往出输送煤炭,一辆车往里输送煤炭。此图可以粗略的理解为线程间通信。
多个线程:两个车如同两个线程。
同一资源:煤炭为同一资源。
任务不同:一辆车往里送煤炭,一辆车往出送煤炭。则两个线程任务不同。
/**
* 煤炭类[同一资源]
*/
class Coal
{
String carName;
String weight;
}
/**
* 往里输送煤炭类
*/
class InputCar implements Runnable
{
Coal coal;
public InputCar(Coal coal)
{
this.coal = coal;
}
@Override
public void run()
{
while(true)
{
coal.weight = "输入10吨";
try
{
Thread.sleep(10);
} catch (InterruptedException e)
{
e.printStackTrace();
}
coal.carName = "输入车";
System.out.println("InputCar : " + coal.carName +" ... "+coal.weight);
}
}
}
/**
* 往外输送煤炭类
*/
class OutputCar implements Runnable
{
Coal coal;
public OutputCar(Coal coal)
{
this.coal = coal;
}
@Override
public void run()
{
while(true)
{
coal.carName = "输出车";
try
{
Thread.sleep(10);
} catch (InterruptedException e)
{
e.printStackTrace();
}
coal.weight = "输出车5吨";
System.out.println("OutputCar : 车次-" + coal.carName +" ... 碳重-"+coal.weight+"吨");
}
}
}
/**
* 测试
*/
public class Test
{
public static void main(String[] args)
{
Coal coal = new Coal();
InputCar inputCar = new InputCar(coal);
OutputCar outputCar = new OutputCar(coal);
Thread thread = new Thread(inputCar);
Thread thread2 = new Thread(outputCar);
thread.start();
thread2.start();
}
}
部分结果如下:
InputCar : 输入车 … 输出车5吨
OutputCar : 车次-输入车 … 碳重-输出车5吨吨
InputCar : 输入车 … 输出车5吨
OutputCar : 车次-输入车 … 碳重-输出车5吨吨
可以看出打印结果是有问题的,此问题的出现请参考
线程Thread(JAVA) 篇三 synchronized(同步)
线程Thread(JAVA) 篇四 synchronized(同步)
修改如下所示:
/**
* 煤炭类[同一资源]
*/
class Coal
{
String carName;
String weight;
}
/**
* 往里输送煤炭类
*/
class InputCar implements Runnable
{
Coal coal;
public InputCar(Coal coal)
{
this.coal = coal;
}
@Override
public void run()
{
while(true)
{
synchronized(coal)
{
coal.weight = "输入10吨";
try
{
Thread.sleep(10);
} catch (InterruptedException e)
{
e.printStackTrace();
}
coal.carName = "输入车";
System.out.println("InputCar : " + coal.carName +" ... "+coal.weight);
}
}
}
}
/**
* 往外输送煤炭类
*/
class OutputCar implements Runnable
{
Coal coal;
public OutputCar(Coal coal)
{
this.coal = coal;
}
@Override
public void run()
{
while(true)
{
synchronized(coal)
{
coal.carName = "输出车";
try
{
Thread.sleep(10);
} catch (InterruptedException e)
{
e.printStackTrace();
}
coal.weight = "输出车5吨";
System.out.println("OutputCar : 车次-" + coal.carName +" ... 碳重-"+coal.weight+"吨");
}
}
}
}
/**
* 测试
*/
public class Test
{
public static void main(String[] args)
{
Coal coal = new Coal();
InputCar inputCar = new InputCar(coal);
OutputCar outputCar = new OutputCar(coal);
Thread thread = new Thread(inputCar);
Thread thread2 = new Thread(outputCar);
thread.start();
thread2.start();
}
}
结果如下:
InputCar : 输入车 … 输入10吨
InputCar : 输入车 … 输入10吨
InputCar : 输入车 … 输入10吨
InputCar : 输入车 … 输入10吨
OutputCar : 车次-输出车 … 碳重-输出车5吨吨
OutputCar : 车次-输出车 … 碳重-输出车5吨吨
OutputCar : 车次-输出车 … 碳重-输出车5吨吨
OutputCar : 车次-输出车 … 碳重-输出车5吨吨
OutputCar : 车次-输出车 … 碳重-输出车5吨吨
这次的打印结果对了,但是这仅仅解决了同步问题,还没到线程间通信问题,现在想要的打印结果是输入10吨和输出5吨相间的效果,如下:
InputCar : 输入车 … 输入10吨
OutputCar : 车次-输出车 … 碳重-输出车5吨吨
InputCar : 输入车 … 输入10吨
OutputCar : 车次-输出车 … 碳重-输出车5吨吨
InputCar : 输入车 … 输入10吨
OutputCar : 车次-输出车 … 碳重-输出车5吨吨
要达到这种效果,需要使用线程的等待唤醒机制,主要涉及到的方法有:
wait(); 让线程处于冻结状态,被wait的线程会被存储到线程池中。
notify() 唤醒线程池中一个任意线程。
notifyAll(); 唤醒线程池中所有的线程。
这三个方法必须定义在同步中:因为这些方法是用于操作线程状态的方法,必须要明确到底操作的是哪个线程上的哪个锁
修改代码如下:
/**
* 煤炭类[同一资源]
*/
class Coal
{
String carName;
String weight;
boolean flag = true;
}
/**
* 往里输送煤炭类
*/
class InputCar implements Runnable
{
Coal coal;
public InputCar(Coal coal)
{
this.coal = coal;
}
@Override
public void run()
{
while(true)
{
synchronized(coal)
{
//当标志位为 true时,输入煤炭
if(coal.flag)
{
coal.weight = "输入10吨";
try
{
Thread.sleep(10);
} catch (InterruptedException e)
{
e.printStackTrace();
}
coal.carName = "输入车";
System.out.println("InputCar : " + coal.carName +" ... "+coal.weight);
coal.flag = false;//标志位置false
coal.notify();//唤醒线程池中的任意一个线程
}
else
{//当标志位为 false时,输出煤炭,输入线程进入等待状态
try
{
coal.wait();
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
}
}
/**
* 往外输送煤炭类
*/
class OutputCar implements Runnable
{
Coal coal;
public OutputCar(Coal coal)
{
this.coal = coal;
}
@Override
public void run()
{
while(true)
{
synchronized(coal)
{
//当标志位为 false时,输出煤炭
if(!coal.flag)
{
coal.carName = "输出车";
try
{
Thread.sleep(10);
} catch (InterruptedException e)
{
e.printStackTrace();
}
coal.weight = "输出车5吨";
System.out.println("OutputCar : 车次-" + coal.carName +" ... 碳重-"+coal.weight+"吨");
coal.flag = true;//标志位置为true
coal.notify();//唤醒线程池中的任意一个线程
}
else
{//当标志位为 true时,输入煤炭,输出线程进入等待状态
try
{
coal.wait();
} catch (InterruptedException e1)
{
e1.printStackTrace();
}
}
}
}
}
}
/**
* 测试
*/
public class Test
{
public static void main(String[] args)
{
Coal coal = new Coal();
InputCar inputCar = new InputCar(coal);
OutputCar outputCar = new OutputCar(coal);
Thread thread = new Thread(inputCar);
Thread thread2 = new Thread(outputCar);
thread.start();
thread2.start();
}
}
输出结果如下:
InputCar : 输入车 … 输入10吨
OutputCar : 车次-输出车 … 碳重-输出车5吨吨
InputCar : 输入车 … 输入10吨
OutputCar : 车次-输出车 … 碳重-输出车5吨吨
InputCar : 输入车 … 输入10吨
OutputCar : 车次-输出车 … 碳重-输出车5吨吨
InputCar : 输入车 … 输入10吨
OutputCar : 车次-输出车 … 碳重-输出车5吨吨
InputCar : 输入车 … 输入10吨
OutputCar : 车次-输出车 … 碳重-输出车5吨吨
InputCar : 输入车 … 输入10吨
OutputCar : 车次-输出车 … 碳重-输出车5吨吨
InputCar : 输入车 … 输入10吨
OutputCar : 车次-输出车 … 碳重-输出车5吨吨
可见达到了预期的效果。这就是线程间的等待唤醒机制的效果。