黑马程序员——多线程(二)
2015-07-25 13:12
465 查看
——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-
当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分(CPU就切换到另外的线程去),还没有执行完,另一个线程参与进来执行。会导致共享数据的错误。
解决办法:加同步
同步代码块
用synchronized关键字来进行定义。
同步代码块格式
synchronized(唯一对象){
需要被同步的代码;
}
对象如同锁,持有锁的线程可以在同步中执行。
没有持有锁的线程即使获取CPU的执行权,也进不去,因为没有获取锁。
好处:解决了多线程的安全问题。
弊端:多个线程需要判断锁,较为消耗资源,
同步的前提:
1,必须要有两个或者两个以上的线程。
2,必须是多个线程使用同一个锁。
同步函数:
所谓的同步函数就是在函数的返回值前面加一个synchronized关键字就是同步函数了。
同步函数的琐是所属函数this,同步函数被静态修饰后,使用的锁是该类对应的字节码文件对象,
举例:延迟加载单例之懒汉式 —面试考点多
线程同步注意的问题:
由于线程同步代码中可能嵌套同步,容易导致的问题就是死锁。程序就停在那里不动了。
线程间通信-等待唤醒机制
wait(),notify(),notifyAll(),都使用在同步中,因为要对持有监视器(锁)的线程操作。
思考:
wait(), notify() ,notifyAll(),用来操作线程的方法为什么定义在了Object类中?
因为这些方法在操作同步中,线程同步,都必须要表示它们所操作线程持有的锁,只有同一个锁上的被等待线程,可以被同一个锁notify唤醒,不可以对不同锁中的线程进行等待唤醒。
也就是说,等待和唤醒必须是同一个锁。所以要使用在同步中,因为只有同步才具有锁。
多线程(守护线程)(后台线程)
线程对象.setDaemon(true);将该线程标记为守护线程或用户线程。
当正在运行的线程都是守护线程时,Java虚拟机退出,程序结束。
注意:一个线程被标示为守护线程,并不是他不运行了,他跟其他线程一样运行。只是当前台线程执行完后,这些线程不会结束。
多线程(Join方法)
Join():当A线程执行到了B线程的.Join()方法时,A线程就会让出CPU执行权,等待直到B线程执行完,A才会执行。
Join可以用来临时加入线程执行。
注意:碰见了谁的Join()方法,就只等谁。等他结束就执行。
多线程(优先级&yield方法)
优先级:线程对象.setPriority(intnewPriority);设置线程优先权,1-10,默认5,越大,抢到CPU执行权机会越大;
(Thread.MAX_PRIORITY, MIN_PRIORITY ,NORM_PRIORITY)
static void yield():暂停当前正在执行的线程,并执行其他线程,Thread.yield();
当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分(CPU就切换到另外的线程去),还没有执行完,另一个线程参与进来执行。会导致共享数据的错误。
解决办法:加同步
同步代码块
用synchronized关键字来进行定义。
同步代码块格式
synchronized(唯一对象){
需要被同步的代码;
}
对象如同锁,持有锁的线程可以在同步中执行。
没有持有锁的线程即使获取CPU的执行权,也进不去,因为没有获取锁。
好处:解决了多线程的安全问题。
弊端:多个线程需要判断锁,较为消耗资源,
同步的前提:
1,必须要有两个或者两个以上的线程。
2,必须是多个线程使用同一个锁。
同步函数:
所谓的同步函数就是在函数的返回值前面加一个synchronized关键字就是同步函数了。
同步函数的琐是所属函数this,同步函数被静态修饰后,使用的锁是该类对应的字节码文件对象,
举例:延迟加载单例之懒汉式 —面试考点多
package com.itheima1; public class danli { private static danli danli = null; private danli() { // TODO Auto-generated constructor stub } public static danli asd() { if(danli==null)//避免每次都判断锁,提高效率 { synchronized(danli.class)//加锁 { if(danli==null){//再次判断,确保对象止创建一次 danli=new danli(); } } } return danli; } }
线程同步注意的问题:
由于线程同步代码中可能嵌套同步,容易导致的问题就是死锁。程序就停在那里不动了。
class MyLock { public static Object locka = new Object(); public static Object lockb = new Object(); } class DeadLockTest implements Runnable { private boolean flag; DeadLockTest(boolean flag) { this.flag = flag; } public void run() { if (flag) { while (true) { synchronized (MyLock.locka) { System.out.println(Thread.currentThread().getName() + "...if locka "); synchronized (MyLock.lockb) { System.out.println(Thread.currentThread().getName() + "..if lockb"); } } } } else { while (true) { synchronized (MyLock.lockb) { System.out.println(Thread.currentThread().getName() + "..else lockb"); synchronized (MyLock.locka) { System.out.println(Thread.currentThread().getName() + ".....else locka"); } } } } } } class Test { public static void main(String[] args) { Thread t1 = new Thread(new DeadLockTest(true)); Thread t2 = new Thread(new DeadLockTest(false)); t1.start(); t2.start(); } }
线程间通信-等待唤醒机制
wait(),notify(),notifyAll(),都使用在同步中,因为要对持有监视器(锁)的线程操作。
思考:
wait(), notify() ,notifyAll(),用来操作线程的方法为什么定义在了Object类中?
因为这些方法在操作同步中,线程同步,都必须要表示它们所操作线程持有的锁,只有同一个锁上的被等待线程,可以被同一个锁notify唤醒,不可以对不同锁中的线程进行等待唤醒。
也就是说,等待和唤醒必须是同一个锁。所以要使用在同步中,因为只有同步才具有锁。
public class Day12Test1 { public static void main(String[] args) { Resouce r = new Resouce(); new Thread(new Producer(r)).start(); new Thread(new Producer(r)).start(); new Thread(new Consumer(r)).start(); new Thread(new Consumer(r)).start(); } } class Resouce{ private String name; private int count = 1; private boolean flag = false; public synchronized void set(String name){ while(flag)//用while判断避免唤醒本方线程 重复消费或者生产 try{ wait(); } 4000 catch(Exception e){ // throw new RuntimeException(); } this.name = name + count++; System.out.println(Thread.currentThread().getName()+"...生产者......"+this.name); flag = true; notifyAll();//唤醒全部线程避免全部等待 } public synchronized void out(){ while(!flag) try{ wait(); } catch(Exception e){ // throw new RuntimeException(); } System.out.println(Thread.currentThread().getName()+"+消费者+"+this.name); flag = false; notifyAll(); } } class Producer implements Runnable{ private Resouce r; Producer(Resouce r){ this.r = r; } public void run(){ while(true){ r.set("汉堡"); } } } class Consumer implements Runnable{ private Resouce r; Consumer(Resouce r){ this.r = r; } public void run(){ while(true){ r.out(); } } }
多线程(守护线程)(后台线程)
线程对象.setDaemon(true);将该线程标记为守护线程或用户线程。
当正在运行的线程都是守护线程时,Java虚拟机退出,程序结束。
注意:一个线程被标示为守护线程,并不是他不运行了,他跟其他线程一样运行。只是当前台线程执行完后,这些线程不会结束。
多线程(Join方法)
Join():当A线程执行到了B线程的.Join()方法时,A线程就会让出CPU执行权,等待直到B线程执行完,A才会执行。
Join可以用来临时加入线程执行。
注意:碰见了谁的Join()方法,就只等谁。等他结束就执行。
多线程(优先级&yield方法)
优先级:线程对象.setPriority(intnewPriority);设置线程优先权,1-10,默认5,越大,抢到CPU执行权机会越大;
(Thread.MAX_PRIORITY, MIN_PRIORITY ,NORM_PRIORITY)
static void yield():暂停当前正在执行的线程,并执行其他线程,Thread.yield();
相关文章推荐
- Python3写爬虫(四)多线程实现数据爬取
- 使用 Syncthing 在多个设备间同步文件
- C#实现多线程的同步方法实例分析
- 浅谈chuck-lua中的多线程
- 科学知识:同步、异步、阻塞和非阻塞区别
- 同步文件备份工具 Super Flexible File Synchronizer Pro v4
- 探讨Ajax中同步与异步之间的区别
- C#简单多线程同步和优先权用法实例
- C#多线程学习之(四)使用线程池进行多线程的自动管理
- C#多线程编程中的锁系统(三)
- C#线程同步的三类情景分析
- C#多线程学习之(六)互斥对象用法实例
- 基于一个应用程序多线程误用的分析详解
- C#多线程学习之(三)生产者和消费者用法分析
- C#多线程学习之(一)多线程的相关概念分析
- C#多线程之Thread中Thread.IsAlive属性用法分析
- C#控制台下测试多线程的方法
- Ruby 多线程的潜力和弱点分析
- C++使用CriticalSection实现线程同步实例
- rsync命令使用总结