线程间通信学习笔记

来源:互联网 发布:手机电池修复软件下载 编辑:程序博客网 时间:2024/05/16 02:24

注:通过网上学习资料整理的笔记

在一个多线程的应用程序中,所有线程共享进程资源,协同工作。所以,线程之间的通信是编写多线程应用的必不可少的环节。
线程之间的通信包括互斥、同步等,它是多线程设计中最难控制的部分,也是关键部分。

实例:两个线程,一个是设置学生属性,另一个获取学生属性。
类似生产者和消费者。
1 学生类
2 测试类
3 设置学生的属性类
4 获取学生的属性类
问题:
只有次数多才使用线程,使用了循环,数据出现了错误。
线程安全问题:
1 有共享数据 s
2 被多个线程调用 设置和获取线程
3 共享数据被多条语句使用 s.name和s.age;

如何解决线程安全问题?
同步代码块
如何找到共享的代码块?
共享数据被多条语句操作的代码。
注意:
加锁必须对多个多个线程加锁,只加一部分没用。
多个线程间必须是同一把锁
目前为止,解决了线程安全问题,数据一出一大片,我们想交替出现,如果没设置能获取吗?不能

为了保证数据的交替出现,java使用等待唤醒机制
* wait()
* notify()
* notifyAll()
* 等待唤醒机制一般使用在同步中
* 举例:
* 抓人游戏
代码:

学生类:public class Student {    private String name ;    private int age;    /**     * 是否有数据     */    private boolean flag = false;    public synchronized void set(String name,int age){        if(this.flag){            try {                this.wait();            } catch (InterruptedException e) {                e.printStackTrace();            }        }        this.name = name ;        this.age = age;        this.flag = true;        this.notify();    }    public synchronized void get() {        if(!this.flag){            try {                this.wait();            } catch (InterruptedException e) {                e.printStackTrace();            }        }        System.out.println(this.name +"****"+ this.age);        this.flag = false;        this.notify();    }}设置学生属性的线程:public class SetStudent implements Runnable {    private Student s;    public SetStudent(Student s) {        this.s=s;    }    public void run() {        int x = 0;        while(true){            if(x%2==0){                s.set("周杰伦", 28);            }else{                s.set("刘德华", 40);            }            x++;        }    }}获取学生属性的线程:public class GetStudent implements Runnable {    private Student s;    public GetStudent(Student s) {        this.s = s;    }    public void run() {        while(true){            s.get();        }    }}测试类:public class StudentTest {    public static void main(String[] args) {        Student s = new Student();        SetStudent ss = new SetStudent(s);        GetStudent gs = new GetStudent(s);        Thread t1 = new Thread(ss);        Thread t2 = new Thread(gs);        t1.start();        t2.start();    }}

以上是使用 synchronized 同步代码解决的。

JDK5出现了Lock接口,可以替代synchronized 同步代码块,使用更方便。
核心部门:

//创建锁private final Lock lock = new ReentrantLock();//Condition 将 Object 监视器方法(wait、notify 和 notifyAll)//分解成截然不同的对象,以便通过将这些对象与任意 Lock 实现组合使用private final Condition condition = lock.newCondition();使用Lock修改的学生类:public class Student {    private String name ;    private int age;    /**     * 是否有数据     */    private boolean flag = false;    private final Lock lock = new ReentrantLock();    private final Condition condition = lock.newCondition();    public  void set(String name,int age){        lock.lock();        if(this.flag){            try {                condition.await();            } catch (InterruptedException e) {                e.printStackTrace();            }        }        this.name = name ;        this.age = age;        this.flag = true;        condition.signal();        lock.unlock();    }    public  void get() {        lock.lock();        if(!this.flag){            try {                condition.await();            } catch (InterruptedException e) {                e.printStackTrace();            }        }        System.out.println(this.name +"****"+ this.age);        this.flag = false;        condition.signal();        lock.unlock();    }}

线程的优先级:setProperty(int x )和getProperty()
更改线程优先级只能在一定程度下多执行下,并不能完全保证。
默认是5,范围1到10

加入线程:join()
等待该线程终止,其他线程都等待加入线程执行完再执行。

等待线程: yield()
暂停当前正在执行的线程对象,并执行其他线程,让线程尽可能的和谐执行,但并不能保证等待唤醒机制的效果。(静态方法)

守护线程:setDaemon(boolean on)
将该线程标记为守护线程或用户线程。当正在运行的线程都是守护线程时,Java 虚拟机退出。如坦克大战。

0 0
原创粉丝点击