一、数据共享
使用Thread对同一个可运行对象r创建了三个线程,三个线程共享了一个数据
package com.runbable;
//操作同一对象实现数据共享
//以银行取钱为例
public class Thread002 implements Runnable{
//定义私有变量
private int money=10000;
//定义取款金额
int n;
Thread002(int n){
this.n=n;
System.out.println("取款金额为"+this.n+"元");
}
public void run(){
while(true) {
if(money>0) {
money -= n;
System.out.println(Thread.currentThread().getName()+"取款后"+"剩余" + money + "元");
}else{
System.exit(0);
}
}
}
}
class Thread002test{
public static void main(String[] args) {
//创建一个对象
Thread002 r=new Thread002(1000);
//将对象由Thread创建三个线程
Thread t1=new Thread(r,"丈夫");
Thread t2=new Thread(r,"妻子");
Thread t3=new Thread(r,"父亲");
//开始执行线程
t1.start();
t2.start();
t3.start();
try{
Thread.sleep(1000);
}catch(InterruptedException e){
System.out.println("线程休眠失败");
}
System.out.println("主线程结束");
}
}
结果:
取款金额为1000元
妻子取款后剩余8000元
丈夫取款后剩余8000元
父亲取款后剩余7000元
妻子取款后剩余6000元
父亲取款后剩余4000元
丈夫取款后剩余5000元
父亲取款后剩余2000元
妻子取款后剩余3000元
父亲取款后剩余0元
丈夫取款后剩余1000元
以上结果怎么看都别扭,这是因为数据虽然共享了,但顺序还是很奇怪,几个线程自己干自己的,没有交流,不安全,下面的线程同步可以解决此问题
以上代码测试类中主线程里面的sleep()方法并没有执行,甚至主线程都没有执行完全就被强制结束了,这是因为在封装类中使用了System.exit(0),当money小于0时,所有线程被强制结束,主线程没有执行完全就结束
二、线程同步
以上我们知道数据共享是存在很多问题的,很不合逻辑,或者说不安全,这是因为一个线程在运行时,另一个线程可能也在运行,交叉操作,当一个线程操作完数据后,数据还没有更新,另一个线程也开始操作,导致逻辑混乱。
为解决这种问题,我们希望在对共享数据进行操作时,这个操作应该是“原子操作”,即在当前线程操作时,不允许其他线程进入,这样每次得到的数据都是同步的,这就是线程同步
Java提供了“锁”机制对线程同步进行支持,如synchronized锁
一、同步代码块
synchronized(同步对象){
需要同步的代码块;
}
一、同步代码块
这里使用需要一个对象锁
二、同步方法
synchronized void fun(){
}
同步代码块
//实例化一个对象作为锁
Object mylock=new Object();
synchronized ("mylock"){
}
同步方法
public synchronized void run() {
}
结果
取款金额为1000元
丈夫取款后剩余9000元
妻子取款后剩余8000元
妻子取款后剩余7000元
妻子取款后剩余6000元
妻子取款后剩余5000元
妻子取款后剩余4000元
妻子取款后剩余3000元
妻子取款后剩余2000元
妻子取款后剩余1000元
妻子取款后剩余0元
此时线程同步,符合逻辑
三、线程通信
由于线程A和线程B持有同一个类的对象object,尽管这两个线程需要调用不同的方法,但是它们是同步执行的
比如:线程B需要等待线程A执行完了methodA()方法之后,它才能执行methodB()方法。这样,线程A和线程B就实现了 通信。
wait()、notify()和notifyAll()
方法wait():使当前执行代码的线程进行等待,在调用wait()之前,线程必须获得该对象的对象级别锁,即只能在同步方法或同步块中调用wait()方法。在执行wait()方法后,当前线程释放锁。
方法notify():也要在同步方法或同步块中调用,即在调用前,线程也必须获得该对象的对象级别锁。唤醒等待的第一个线程
方法notufyAll():唤醒等待的所有线程,按优先级执行
总结:wait使线程停止运行,而notify使停止的线程继续运行