目录
一、主线程与子线程基础通信
1.1 主线程向子线程传递数据
二、子线程向主线程返回数据
2.1 通过共享变量方式
2.2 同步块中使用wait/notify机制
2.3 Lock和Condition实现线程通信机制
一、主线程与子线程基础通信
1.1 主线程向子线程传递数据
-
通过构造函数传递参数:主线程通过UserThread的构造函数将数据a传递给子线程
package com.demo6;public class Test {public static void main(String[] args) {System.out.println(Thread.currentThread().getName()+",主线程");int a = 10;UserThread u = new UserThread(a);u.start();}
}
package com.demo6;public class UserThread extends Thread{int a ;public UserThread(int a){this.a = a;}public void run(){System.out.println(Thread.currentThread().getName()+",执行run方法"+",a的值为:"+a);}}
-
输出结果:主线程创建子线程后,子线程输出接收到的参数值
二、子线程向主线程返回数据
2.1 通过共享变量方式
-
sleep等待:主线程通过sleep等待子线程完成计算
-
共享变量:子线程将计算结果存储在成员变量中,主线程通过getter方法获取
-
缺点:sleep时间难以精确控制,可能等待过长或过短
package com.demo7;public class Test {public static void main(String[] args) {UserThread ut =new UserThread();ut.start();try {Thread.sleep(5*1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}System.out.println("主线程通过getter方法获取的值为: "+ut.getSum());}}
package com.demo7;public class UserThread extends Thread{private int sum = 0;public void run(){for(int i=0;i<=100;i++){this.sum +=i;}}public int getSum(){return this.sum;}}
运行结果:
2.2 同步块中使用wait/notify机制
-
同步协作:主线程和子线程使用同一个对象锁进行同步
-
wait/notify机制:主线程等待,子线程完成后通知主线程
(1)当主线程持有的是当前线程类对象的锁,如果是当前线程类对象的自己this和父类(Object/Thread.class/接口父类.class),都可以通知解锁。 都可以显示的或隐式的写notify。
package com.demo13;public class Test {public static void main(String[] args) {UserThread u = new UserThread();u.start();//线程通信的必须的条件是:同一个对象//如果持有的是当前线程类对象的锁,如果是当前线程类对象的自己this和父类,都可以通知解锁//都可以显示的或隐式的写notifysynchronized (u) {try {//主线程持有u对象的锁,被阻塞u.wait();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}System.out.println("主线程获取的值为:"+u.getSum());}}}
package com.demo13;public class UserThread extends Thread implements IUser{private int sum = 0;Object obj = new Object();public void run(){// synchronized (this) {
// for(int i=0;i<=100; i++)
// {
// sum+=i;
// }
// this.notify();
// }// synchronized (Thread.class) {
// for(int i=0;i<=100; i++)
// {
// sum+=i;
// }
// }// synchronized (obj) {
// for(int i=0;i<=100; i++)
// {
// sum+=i;
// }
// }synchronized (IUser.class) {for(int i=0;i<=100; i++){sum+=i;}}}public int getSum(){return this.sum;}}
package com.demo13;public interface IUser {}
运行结果:
(2)当主线程持有的是非线程类对象的锁,子线程持有的也只能是非线程类对象的锁。这是只能显示的写notify。
package com.demo13;public class Test {public static void main(String[] args) {User u1 = new User();UserThread u = new UserThread(u1);u.start();synchronized (u1) {try {//主线程持有u1对象的锁,内阻塞u1.wait();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}System.out.println("主线程获取的值为:"+u.getSum());}}}
package com.demo13;public class UserThread extends Thread implements IUser{private int sum = 0;User u1;public UserThread(User u1) {this.u1 = u1;}public void run(){synchronized (u1) {for(int i=0;i<=100; i++){sum+=i;}//显示解锁u1.notify();}}public int getSum(){return this.sum;}}
package com.demo13;public class User {}
运行结果:
如果子线程又new了User类对象u1,此时主线程和子线程的u1不是同一个对象,会发生死锁:
2.3 Lock和Condition实现线程通信机制
这是一种基于明锁(Lock)和条件变量(Condition)的线程通信机制,属于JUC包中的高级同步机制。
工作流程:
-
创建锁和条件:主线程创建ReentrantLock和Condition对象
-
传递资源:将锁和条件传递给子线程
-
主线程等待:主线程获取锁后调用cond.await()进入等待状态
-
子线程执行:子线程获取锁,执行计算任务
-
发送信号:子线程完成任务后调用cond.signal()唤醒主线程
-
结果获取:主线程被唤醒后获取并输出计算结果
package com.demo31;import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class Test {public static void main(String[] args) {Lock lock = new ReentrantLock();// 通过锁创建条件变量Condition cond =lock.newCondition();UserThread u1 = new UserThread(lock,cond);u1.start();lock.lock();try {// 主线程等待条件信号cond.await();// 收到信号后输出计算结果System.out.println(u1.getSum());} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}// 手动释放锁lock.unlock();}}
package com.demo31;import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;public class UserThread extends Thread {private Lock lock;private int sum;private Condition cond;public UserThread(Lock lock,Condition cond) {this.lock = lock;this.cond =cond;}public void run() {lock.lock();for (int i = 0; i <= 100; i++) {try {Thread.sleep(200);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}this.sum += i;}// 发送条件信号,唤醒等待的线程this.cond.signal();// 释放锁this.lock.unlock();}public int getSum(){return this.sum;}}
运行结果: