黑马程序员_多线程2
来源:互联网 发布:2013淘宝男装店铺排行 编辑:程序博客网 时间:2024/06/10 19:38
-----------------------------------------------------------------android培训、java培训、期待与您交流! ---------------------------------------------------------------
1. 多线程的安全问题:synchronized(同步问题)
① 多线程同步代码块
② 多线程同步函数 :同步关键字作为修饰符修饰函数
同步代码块:
synchronized(对象)
{
需要被同步的代码
}
同步的前提(重要)
1. 必须有两个或两个以上线程
2. 必须是多个线程使用同一个锁
同步代码块弊端:因为线程每次都要对锁进行判断,比较消耗资源(该消耗在使用允许范围内)
同步函数
当synchronized修饰函数时,并没有指定锁,其默认的锁为this
如果同步函数被static静态修饰时,因为静态方法中还没有this(即还没有对象),静态进内存中还没有本类对象,但是一定有该类对应的字节码文件对象-----即:类名.class 该对象的类型是Class,使用可以使用该类对象.clsss文件为锁
懒汉式的安全问题
//饿汉式class Single {private static final Single s = new Single();private Single(){}public static Single getInstance() {return s;}}因为饿汉式在开始时就已经创建了Single实例,所以并不会出现多线程的安全问题
//懒汉式---存在多线程安全问题class Single {private static Single s = null;private Single() {}public static Single getInstance() {if(s == null)s = new Single();return s;}}在多线程情况下,判断single对象是否存在时就有安全隐患所以需要加锁同步
//懒汉式安全方法class Single {private static Single s = null;private Single() {}public static Single getInstance() {if(s == null) {synchronized(Single.class) {//静态方法的锁没有this,使用该类所属的字节码文件对象作为锁if(s == null)s = new Single();}}return s;}}
线程通信同步安全问题
/*线程通信优化*/class Res {private String name;private String sex;privateboolean flag = false;public synchronized void set(String name, String sex) {if(flag)try{this.wait();}catch(Exception e) {}this.name = name;this.sex = sex;flag = true;this.notify();}public synchronized void out() {if(!flag)try{this.wait();}catch(Exception e) {}System.out.println(this.name + "=============" + this.sex);flag = false;this.notify();}}class Output implements Runnable {Res r;Output(Res r) {this.r = r;}public void run() {while(true) {r.out();}}}class Input implements Runnable {Res r;Input(Res r) {this.r = r;}public void run() {int x = 0;while(true) {if(x == 0) r.set("Tom", "man");elser.set("丽丽", "女女女女女女");x = (x + 1) % 2;}}}class InputOutputDemo2 {public static void main(String[] args) {Res r = new Res();Input in = new Input(r);Output out = new Output(r);Thread t1 = new Thread(in);Thread t2 = new Thread(out);t1.start();t2.start();}}在两个线程通信时,使用同步共享资源后通过等待和唤醒完成了线程通信
线程通信共享问题----等待唤醒机制
wait()
notify()
notifyAll()
wait()与notify(),notifyAll()----并不是Tread类中的,而是其父类Object里的,且该三个方法一般用于同步代码中----并且需要标识其对应的锁
为什么该三个方法定义在Object类中呢?
因为当你在同步代码时要标识他们所操作线程所操作的锁,而这个锁不一定唯一可以是任意对象,所以放在所有类的父类Object。
多个生产者消费者同步共享安全问题---------while循环和notifyAll()
当多个线程操作共享数据时通过上边的两个线程通信if判断标识,notify唤醒线程会出现安全问题所以需改进代码
class Resource {private String name;private int count = 1;private boolean flag = false;public synchronized void set(String name) {while(flag)//if改用while循环判断try{this.wait();}catch(Exception e) {}this.name = name + "=====" + count++;System.out.println(Thread.currentThread().getName() + "-----------Producer----------" + this.name);flag = true;this.notifyAll();//唤醒等待队列的所有线程}public synchronized void out() {while(!flag)//if改用while循环判断try{this.wait();}catch(Exception e) {}System.out.println(Thread.currentThread().getName() + "------Consumer-----" + this.name);flag = false;this.notifyAll();//唤醒等待队列的所有线程}}class Producer implements Runnable {private Resource r;Producer(Resource r){this.r = r;}public void run () {while(true) {r.set("Product : Tool");}}}class Consumer implements Runnable {private Resource r;Consumer(Resource r){this.r = r;}public void run() {while(true) {r.out();}}}class ProducerConsumerDemo {public static void main(String[] args) {Resource r = new Resource();Producer producer = new Producer(r);Consumer consumer = new Consumer(r);Thread proThread1 = new Thread(producer);Thread proThread2 = new Thread(producer);Thread conThread1 = new Thread(consumer);Thread conThread2 = new Thread(consumer);proThread1.start();proThread2.start();conThread1.start();conThread2.start();}}
多个生产者消费者同步共享JDK1.5 新特性---------java.util.concurrent.locks---Lock接口----Condition接口
Lock接口替代synchronized
Condition接口替代Object的wait,notify,notifyAll-----------使用方法await,signal,signalAll
Lock接口三个实现类
|--ReentrantLock
|--ReentrantReadWriteLock.ReadLock
|--ReenttrantReadWriteLock.WriteLock
用JDK1.5的Lock锁改动多个线程同步的代码
//这只是对原来代码的改用并没有用到新的特点import java.util.concurrent.locks.*;class Resource {private String name;private int count = 1;private boolean flag = false;//创建锁private Lock lock = new ReentrantLock();private Condition condition = lock.newCondition();public void set(String name) throws InterruptedException {lock.lock();try {while(flag)//try{this.wait();}catch(Exception e) {}condition.await();this.name = name + "=====" + count++;System.out.println(Thread.currentThread().getName() + "-----------Producer----------" + this.name);flag = true;//this.notifyAll();condition.signalAll();} finally {//因为锁是资源最后一定要释放lock.unlock();}}public void out() throws InterruptedException{lock.lock();try {while(!flag)//try{this.wait();}catch(Exception e) {}condition.await();System.out.println(Thread.currentThread().getName() + "------Consumer-----" + this.name);flag = false;//this.notifyAll();condition.signalAll();} finally {lock.unlock();}}}class Producer implements Runnable {private Resource r;Producer(Resource r){this.r = r;}public void run () {while(true) {try {r.set("Product : Tool");} catch(InterruptedException e) {}}}}class Consumer implements Runnable {private Resource r;Consumer(Resource r){this.r = r;}public void run() {while(true) {try {r.out();} catch(InterruptedException e) {}}}}class ProducerConsumerJDKenhanceDemo {public static void main(String[] args) {Resource r = new Resource();Producer producer = new Producer(r);Consumer consumer = new Consumer(r);Thread proThread1 = new Thread(producer);Thread proThread2 = new Thread(producer);Thread conThread1 = new Thread(consumer);Thread conThread2 = new Thread(consumer);proThread1.start();proThread2.start();conThread1.start();conThread2.start();}}
await与signal 不同于wait与notify
await可以等待指定的condition
signal可以唤醒指定的condition
所以新版本的Lock实现同步代码如下
import java.util.concurrent.locks.*;class Resource {private String name;private int count = 1;private boolean flag = false;//创建锁private Lock lock = new ReentrantLock();private Condition conditionProducter = lock.newCondition();private Condition conditionConsumer = lock.newCondition();public void set(String name) throws InterruptedException {lock.lock();try {while(flag)//try{this.wait();}catch(Exception e) {}conditionProducter.await();this.name = name + "=====" + count++;System.out.println(Thread.currentThread().getName() + "-----------Producer----------" + this.name);flag = true;//this.notifyAll();conditionConsumer.signal();} finally {//因为锁是资源最后一定要释放lock.unlock();}}public void out() throws InterruptedException{lock.lock();try {while(!flag)//try{this.wait();}catch(Exception e) {}conditionConsumer.await();System.out.println(Thread.currentThread().getName() + "------Consumer-----" + this.name);flag = false;//this.notifyAll();conditionProducter.signal();} finally {lock.unlock();}}}class Producer implements Runnable {private Resource r;Producer(Resource r){this.r = r;}public void run () {while(true) {try {r.set("Product : Tool");} catch(InterruptedException e) {}}}}class Consumer implements Runnable {private Resource r;Consumer(Resource r){this.r = r;}public void run() {while(true) {try {r.out();} catch(InterruptedException e) {}}}}class ProducerConsumerJDKenhanceDemo2 {public static void main(String[] args) {Resource r = new Resource();Producer producer = new Producer(r);Consumer consumer = new Consumer(r);Thread proThread1 = new Thread(producer);Thread proThread2 = new Thread(producer);Thread conThread1 = new Thread(consumer);Thread conThread2 = new Thread(consumer);proThread1.start();proThread2.start();conThread1.start();conThread2.start();}}
停止线程
原有的stop方法已经过时,如何停止线程?
只有一种方法,run方法结束。
开启多线程运行,运行代码通常是循环结构,只要控制循环,就可以让run方法结束,也就是线程结束。
代码操作----在循环中使用boolean型标记,对外提供一个修改标记方法
特殊情况:
多线程中当线程冻结时,不会读到标记,线程就无法停止
如何解决这个问题?
interrupt对冻结状态清除,强制让线程回复到运行状态中,这样就可以修改标记,让线程结束
守护线程(后台线程)
setDanmon()设置成守护线程---必须在线程启动前设置
join方法
当A线程执行到了B线程的join方法时,A线程等待,等B线程执行完,A才会执行
Join可以临时加入线程
线程优先级----1---10
默认优先级5
可以通过setPriority()设置线程优先级
MAX_PRIORITY
MIN_PRIORITY
NORM_PRIORITY
yield(): 暂停当前正在执行的线程对象,并执行其他线程。
- 黑马程序员_多线程2
- 黑马程序员_多线程2
- 黑马程序员_多线程2
- 黑马程序员_多线程2
- 黑马程序员_多线程2
- 黑马程序员_多线程2
- 黑马程序员_多线程2
- 黑马程序员_多线程2
- 黑马程序员_多线程
- 黑马程序员_多线程
- 黑马程序员_多线程
- 黑马程序员_多线程
- 黑马程序员_多线程
- 黑马程序员_多线程
- 黑马程序员_多线程
- 黑马程序员_多线程
- 黑马程序员_多线程
- 黑马程序员_多线程
- 关于“JSONObject cannot be resolved to a type”问题的解决
- Unable to execute dex: java.nio.BufferOverflowException
- 数字图像处理—算术运算基本作用及模板(样板,窗口,滤波器)运算
- UVa10120 - Gift?!
- 篮桥杯,翻硬币 (贪心)
- 黑马程序员_多线程2
- 记一种TDD方式:红绿憋,红绿再憋
- POJ 2559 单调栈
- WPF设置Image控件的图片淡入淡出更换
- 副老大的待遇
- Remove Duplicates from Sorted Array - LeetCode
- OpenThreads
- [IOS]UITextField中设置placeholder字体颜色
- WinSock网络编程学习(二)计算校验和程序