(笔记九)多线程、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
分析: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
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.获取当前程序所有线程
多线程在处理同一资源,但任务却不同
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();
}
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());}
- (笔记九)多线程、Lock、停止线程
- 多线程提高、Lock、停止线程
- Java笔记 - 多线程 - 停止线程
- Java多线程学习笔记—线程停止
- JAVA多线程学习笔记<3> 停止线程
- Java 多线程 学习笔记 线程的停止
- java 多线程 停止线程
- 多线程(停止线程)
- 多线程学习-停止线程
- 多线程(停止线程)
- JAVA-多线程-停止线程
- 多线程---停止线程
- java多线程 ---- 停止线程
- Java多线程-停止线程
- C#笔记22:多线程之停止或取消线程
- C#笔记22:多线程之停止或取消线程
- java多线程学习笔记(八) ——线程停止(interrupt)
- java多线程编程核心技术笔记-停止线程interrupt()方法
- Uva 11218 - KTV
- 在action中刷新ztree
- Ural 1098 Questions
- 填空学指针
- 基于最低有效位 把信息隐藏到图片中
- (笔记九)多线程、Lock、停止线程
- 一位软件工程师的6年总结
- SQL指令— CONCAT(字符串连接函数)
- POj 1883 数字排列 next_permutation解决之
- 设计模式之一 :单例设计模式
- 使用python处理文件
- C# 线程
- 安装Nessus
- 2013编程之美-资格赛-传话游戏-编程有问题 艹 理解错题意 不过还好 熟悉了《map》结构