------- android培训、java培训、期待与您交流! ----------
黑马程序员------多线程(二)
1.1 同步代码块:Java对多线程的安全问题提供了专业的解决方式
格式:
synchronized(对象){ 需要被同步的代码(共享数据)
}
对象如同锁。持有锁的线程可以在同步中执行。没有持有锁的线程即使获取cpu的执行权,也进不去,因为没有获取锁。
火车上的卫生间---经典。
同步的前提:1,必须要有两个或者两个以上的线程。2,必须是多个线程使用同一个锁。
必须保证同步中只能有一个线程在运行。
好处:解决了多线程的安全问题。
弊端:多个线程需要判断锁,较为消耗资源
示例1:
1 class Ticket implements Runnable 2 { 3 private int tick = 1000; 4 Object obj = new Object(); 5 public void run() 6 { 7 while(true) 8 { 9 synchronized(obj) 10 { 11 if(tick>0) 12 { 13 //try{Thread.sleep(10);}catch(Exception e){} 14 System.out.println(Thread.currentThread().getName()+"....sale : "+ tick--); 15 } 16 } 17 } 18 } 19 } 20 21 22 class TicketDemo2 23 { 24 public static void main(String[] args) 25 { 26 27 Ticket t = new Ticket(); 28 29 Thread t1 = new Thread(t); 30 Thread t2 = new Thread(t); 31 Thread t3 = new Thread(t); 32 Thread t4 = new Thread(t); 33 t1.start(); 34 t2.start(); 35 t3.start(); 36 t4.start(); 37 38 39 } 40 }
1.2同步函数
同步函数格式:
public synchronized void show()
{
}
如何找问题?
1.明确哪些代码是多线程运行代码
2.明确共享数据
3.明确多线程运行代码中哪些语句是操作共享数据的?
同步函数的锁是 this。函数需要被对象调用,那么函数都有一个所属对象引用。
想让线程停一下
Thread.sleep(10);
如果同步函数被静态修饰后,使用的锁是 class
synchronized (对象名.class)
1.3 死锁:
同步中嵌套同步,可能会发生,该怎么解决
是由于 两个线程相互等待 对方已被锁定的资源
循环等待条件:第一个线程等待其它线程,后者又在等待第一个线程。
避免死锁的一个通用的经验法则是:当几个线程都要访问共享资源A、B、C时,
保证使每个线程都按照同样的顺序去访问它们,比如都先访问A,在访问B和C。
1.4 线程间通信:多个线程在操作同一个资源,但是操作的动作不同。
1.是不是两个或两个以上的线程。解决办法 两个线程都要被同步。2.是不是同一个锁。解决办法 找同一个对象作为锁。
等待唤醒机制。
wait后,线程就会存在线程池中,notify后就会将线程池中的线程唤醒。notifyAll();唤醒线程池中所有的线程。实现方法 :
给资源加个标记 flag
synchronized(r){ while(r.flag)//多个生产者和消费者 if(r.flag)//一个生产者和消费者 r.wait(); 代码 r.flag=true; r.notify(); r.notifyAll();}
上面三种方法都使用在同步中,因为要对持有监视器(锁)的线程操作。所以要使用在同步中,因为只有同步才具有锁。
为什么这些操作线程的方法要定义在object类中呢?因为这些方法在操作同步中线程的是偶,都必须要表示它们所操作线程只有的锁。只有同一个锁上的被等待线程,可以被同一个锁上的notify唤醒,不可以对不同锁中的线程进行唤醒。
也就是说,等待和唤醒必须是同一个锁,而锁可以是特意对象,可以被任意对象调用的方法定义在Object类中。
1.5 Lock接口 多生产者和消费者 JDK1.5版本升级版(示例2) Lock 替代了synchronized Condition 替代了 Object监视器方法
好处:将同步synchronized 替换成了 Lock 将object中的wait notify notifyAll 替换成了 Condition对象 该对象可以Lock锁进行获取。一个锁可以对应多个Condition对象注意:释放锁的工作一定要执行
示例2
1 private Lock lock=new ReentrantLock(); 2 private Condition condition =lock.newCondition(); 3 4 public void cet(String name ) throws 5 { 6 lock.lock(); 7 try 8 { 9 while(flag) 10 contidition.await(); 11 this.name=name+"--"+count++; 12 13 sop(Thread.currentThread().getName()+"...生产者..."+this.name) 14 flag=true; 15 condition.signalAll(); 16 17 } 18 finally 19 { 20 lock.unlock(); 21 22 } 23 }
1.6 停止线程、守护线程、Join方法:
停止线程:
run方法结束,就会停止线程,开启多线程运行,运行代码通常是循环结构。只要控制住循环,就可以让线程结束。
方法:改变标记。
特殊情况,改变标记也不会停止的情况。
将处于冻结状态的线程恢复到运行状态。interrupt(); 中断线程。
守护线程:SetDaemon将线程标记为守护线程或用户线程。在启动线程前调用 。当线程都为守护线程后,JVM退出。
Join方法:
t.join();抢过cpu执行权。
当A线程执行到了B线程的join方法时,A就会等待,等B线程执行完,A才会执行。Join可以用来临时加入线程执行。
优先级:SetPriority(1-10)设置优先级。Thread.MAX_PRIORITY 10Thread.MIN_PRIORITY 1Thread.NORM_PRIORITY 5
yield方法:暂停当前正在执行的线程对象,并执行其他线程。
开发中应用::保证以下三个代码同时运行。
示例3:
1 new Thread() 2 { 3 for(int x=0;x<100;x++) 4 { 5 sop(Thread.currentThread().getName()) 6 7 } 8 }.start(); 9 10 11 for(int x=0;x<100;x++) 12 { 13 sop(Thread.currentThread().getName()) 14 15 } 16 17 Runnable r=new Runnable() 18 { 19 public voud run(){ 20 for(int x=0;x<100;x++) 21 { 22 sop(Thread.currentThread().getName()) 23 24 } 25 26 } 27 }; 28 29 new Thread(r).start();
转载于:https://www.cnblogs.com/jiandonn/p/4576338.html
相关资源:各显卡算力对照表!