(笔记九)多线程、Lock、停止线程

来源:互联网 发布:无人驾驶近年数据 编辑:程序博客网 时间:2024/06/10 01:29
1.线程间通信
多线程在处理同一资源,但任务却不同

2.obj.wait(),obj.notify(),obj.notifyAll()
1)必须存在synchronized(Obj)语句块中

2)锁可以是任何对象,这些方法定在在Object中

3)wait:线程在获取对象锁后,通过wait方法主动释放对象锁,同时本线程阻塞。直到有其它线程调用该对象锁的notify()唤醒该线程,才能继续获取对象锁,并继续执行。(线程存入线程池)

4)notify:相当于对象锁的唤醒操作。调用后,并不是马上就释放对象锁,而是在相应的synchronized(){}语句块执行结束后,JVM会在wait()对象锁的线程中随机选取一线程,赋予其对象锁,唤醒线程(★★★继续执行,而不是重新执行)。

2.wait()与sleep()区别
1)前者释放cpu执行权并释放锁,后者释放cpu执行权 ,不释放锁

2)wait可以指定时间也可以不指定,sleep必须指定

3.例子
两个线程同时操作对象,先输入然后输出,循环显示
Person.java
package mypackage;public class Person {String name;String sex;boolean flag;}
input.java
package mypackage;public class Input implements Runnable {Person p;public Input(Person p) {this.p = p;}public void run() {int x = 0;while (true) {synchronized (p) {if(p.flag){try {p.wait();} catch (InterruptedException e) {e.printStackTrace();}}if (x % 2 == 0) {p.name = "Tom";p.sex = "male";} else {p.name = "Lily";p.sex = "female";}p.flag=true;p.notify();}x++;}}}
Out.java
package mypackage;public class Out implements Runnable {Person p;public Out(Person p) {this.p = p;}public void run() {while (true) {synchronized (p) {if (!p.flag) {try {p.wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println(p.name + "..." + p.sex);p.flag = false;p.notify();}}}}
Demo.java
import mypackage.*;public class Demo {public static void main(String[] args) {Person p=new Person();Input in=new Input(p);Out out=new Out(p);Thread t1=new Thread(in);Thread t2=new Thread(out);t1.start();t2.start();}}
4.优化Person类
public class Person {private String name;private String sex;privateboolean flag;synchronized void input(String name,String sex){if(flag)try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}this.name=name;this.sex=sex;flag=true;notify();}synchronized void out(){if(!flag)try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("name:"+name+",sex:"+sex);flag=false;notify();}}

5.多个线程同时输入,多个线程同时输出情况下,引发异常(★★★)

在main函数中,创建两个线程t0与t1,执行输入操作;创建两个线程t2与t3,执行输出操作。
分析:t0执行后阻塞-->t1阻塞-->t2执行后阻塞,唤醒t0-->t3阻塞(仅t0运行)-->
t0输入数据后,并没有输出(异常!!!),唤醒t1,再次输入。

原因:if判断只执行一次,在t1阻塞后重新得到执行权,不会再次判断是否要运行,导致不该运行的线程运行,导致数据异常。

解决:将if换成while,解决判断是否运行,但会导致死锁,可将notify换成notifyAll解决

6.Lock(JDK1.5特性)
1)提供了比使用synchronized方法和语句更广泛的锁定操作,允许更灵活的结构,支持多个Condition对象(支持多个监视器对象),Condition代替Object中的wait,notify,notifyAll。

2)将synchronized隐式实现转变为Lock对象的显示实现

3)使用
Lock l = 实现;
 l.lock();
 try

 {
 }
finally {
      l.unlock();
 } 

 4)演示
import java.util.concurrent.locks.*;public class Product {String name;int Id;boolean flag;int no = 1;// 创建锁对象Lock l = new ReentrantLock();// 通过已有锁对象创建该锁上的监视器对象,一个监视生产者,一个监视销售者Condition in = l.newCondition();Condition out = l.newCondition();void input(String name) {l.lock();try {while (flag)try {in.await();} catch (InterruptedException e) {e.printStackTrace();}this.name = name;this.Id = no++;System.out.println("生产:" + name + "," + Id);flag = true;out.signal();} finally {l.unlock();}}void out() {l.lock();try {while (!flag)try {out.await();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("销售:" + name + ",id:" + Id + ",继续加油");flag = false;in.signal();} finally {l.unlock();}}}

7.停止线程
1)stop方法,涉及安全问题,已过时
2)run方法结束,通常任务中会有循环结构,控制循环标记,但如果线程处于堵塞状态,无法读取标记,则无法结束
3)interrupt方法,将线程从阻塞状态强制恢复到运行状态来,让线程具备cpu执行资格,但会发生InterruptException,可以在catch中处理循环标记

8.守护线程
setDaemon方法必须在启动线程前调用,当正在运行的线程都是守护线程时(),Java 虚拟机退出。
非守护线程可以理解为前台线程,守护线程守护前台线程,前台线程都结束,守护线程也结束。

9.join
当前线程等待该线程终止,后运行

10.经典面试题
3个线程顺序打印10次ABC

11.获取线程状态方法getState() 

对应枚举 Thread.State(6种状态)

12.获取当前程序所有线程
ThreadGroup topGroup = null;ThreadGroup group = Thread.currentThread().getThreadGroup();// 遍历线程组树,获取根线程组while (group != null) {topGroup = group;group = group.getParent();}// 此线程组中活动线程的估计数int estimatedSize = topGroup.activeCount();System.out.println("active:" + estimatedSize);Thread[] slackList = new Thread[estimatedSize];// 获取根线程组的所有线程int actualSize = topGroup.enumerate(slackList);//遍历for (Thread t : slackList) {System.out.println("ID:" + t.getId() + ",Name:" + t.getName()+ ",isAlive:" + t.isAlive());}

原创粉丝点击