标签:
黑马程序员------多线程(二)
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 10
Thread.MIN_PRIORITY 1
Thread.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();
标签:
原文地址:http://www.cnblogs.com/jiandonn/p/4576338.html