Java笔记(二)

10. 

  public  protected default private
同一个类中
同一个包中  
子类    
不同包中      

 

11. 线程:

 static Thread currentThread():获取当前线程对象

 getName():获取线程名称

 设置线程名称:setName()或者构造函数

 创建线程的方式:

  1. 继承Thread类

    (1)定义类,继承Thread

    (2)复写Thread类中的void run()方法(因为Thread类用于描述线程,该类就定义了一个功能,用于存储线程要运行的代码。该存储功能就是run方法。)

    (3)调用线程的start方法,该方法能启动线程,并能调用run方法

    注:对象.run()仅仅是对象调用方法。而线程创建了,并没有运行;

      对象.start()开启线程并执行该线程的run方法

  2. 实现Runnable接口

    (1)定义类,实现Runnable接口

    (2)覆盖Runnable接口中的run方法。将线程要运行的代码存放在该run方法中

    (3)通过Thread类建立线程对象

    (4)将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数。因为,自定义的run方法所属的对象是Runnable接口的子类对象,所以要让线程去执行指定对象的run方法,就必须明确该run方法所属的对象。

    (5)调用Thread类的start方法开启线程,并调用Runnable接口子类的run方法

  实现方式与继承方式的区别:

   实现方式好处:避免了单继承的局限性。在定义线程时,建议使用实现方式。

   继承Thread:线程代码存放在Thread子类run方法中;实现Runnable:线程代码存放在接口的子类的run方法。

 同步函数的锁是this;静态同步函数的锁是Class对象(类名.class)

 死锁:例:

 1 class DeadLock implements Runnable{
 2     private boolean flag;
 3     DeadLock(boolean flag){
 4         this.flag = flag;
 5     }
 6     public void run(){
 7         if(flag){
 8             while(true){
 9                 synchronized(Lock.locka){
10                     System.out.println("if locka");
11                     synchronized(Lock.lockb){
12                         System.out.println("if lockb");
13                     }
14                 }
15             }
16         }
17         else{
18             while(true){
19                 synchronized(Lock.lockb){
20                     System.out.println("else lockb");
21                     synchronized(Lock.locka){
22                         System.out.println("else locka");
23                     }
24                 }
25             }    
26         }    
27     }
28 }
29 
30 class Lock{
31     public static Object locka = new Object();
32     public static Object lockb = new Object();
33 }
34 
35 public class Demo{
36     public static void main(String[] args) {
37         Thread t1 = new Thread(new DeadLock(true));
38         Thread t2 = new Thread(new DeadLock(false));
39         t1.start();
40         t2.start();
41     }
42 }

 wait()  notify()  notifyAll():

  都使用在同步中,因为要对持有监视器(锁)的线程操作,只有同步才具有锁。

  这些方法在操作同步中线程时,都必须要标识它们所操作线程持有的锁。只有同一个锁上的被等待线程,可以被同一个锁上的notify()唤醒,不可以对不同锁中的线程进行唤醒。也就是说,等待和唤醒必须是同一个锁。而锁可以是任意对象,所以可以被对象调用的方法定义Object类中。

  生产者-消费者问题:

 1 class Resource{
 2     private String name;
 3     private int count = 1;
 4     private boolean flag = false;
 5     
 6     public synchronized void set(String name){
 7         while(flag){
 8             try {
 9                 this.wait();
10             } catch (InterruptedException e) {
11                 e.printStackTrace();
12             }
13         }
14         this.name = name + " ~~ " + count++;
15         System.out.println(Thread.currentThread().getName() + "..生产者.." + this.name);
16         flag = true;
17         this.notifyAll();
18     }
19     
20     public synchronized void out(){
21         while(!flag){
22             try {
23                 this.wait();
24             } catch (InterruptedException e) {
25                 e.printStackTrace();
26             }
27         }
28         System.out.println(Thread.currentThread().getName() + "....消费者...." + this.name);
29         flag = false;
30         this.notifyAll();
31     }
32 }
33 
34 class Producer implements Runnable{
35     private Resource r;
36     Producer(Resource r){
37         this.r = r;
38     }
39     public void run(){
40         while(true){
41             r.set("商品");
42         }
43     }
44 }
45 
46 class Consumer implements Runnable{
47     private Resource r;
48     Consumer(Resource r){
49         this.r = r;
50     }
51     public void run(){
52         while(true){
53             r.out();
54         }
55     }
56 }
57 
58 public class Demo{
59     public static void main(String[] args) {
60         Resource r = new Resource();
61         Thread t1 = new Thread(new Producer(r));
62         Thread t2 = new Thread(new Producer(r));
63         Thread t3 = new Thread(new Consumer(r));
64         Thread t4 = new Thread(new Consumer(r));
65         t1.start();
66         t2.start();
67         t3.start();
68         t4.start();
69     }
70 }

 对于多个生产者和消费者。定义while判断标记的原因:让被唤醒的线程再一次判断标记。

             定义notifyAll的原因:需要唤醒对方线程。如果只用notify,容易                                        出现只唤醒本方线程的情况。导致程序中的所有线程都等待。

生产者-消费者(升级版):

 1 import java.util.concurrent.locks.Condition;
 2 import java.util.concurrent.locks.Lock;
 3 import java.util.concurrent.locks.ReentrantLock;
 4 
 5 class Resource{
 6     private String name;
 7     private int count = 1;
 8     private boolean flag = false;
 9     private Lock lock = new ReentrantLock();
10     private Condition condition_pro = lock.newCondition();
11     private Condition condition_con = lock.newCondition();
12     
13     public void set(String name) throws InterruptedException{
14         lock.lock();
15         try{
16             while(flag){
17                 condition_pro.await();
18             }
19             this.name = name + " ~~ " + count++;
20             System.out.println(Thread.currentThread().getName() + "..生产者.." + this.name);
21             flag = true;
22             condition_con.signal();
23         }finally{
24             lock.unlock();
25         }
26     }
27     
28     public void out() throws InterruptedException{
29         lock.lock();
30         try{
31             while(!flag){
32                 condition_con.await();
33             }
34             System.out.println(Thread.currentThread().getName() + "....消费者...." + this.name);
35             flag = false;
36             condition_pro.signal();
37         }finally{
38             lock.unlock();
39         }
40     }
41 }
42 
43 class Producer implements Runnable{
44     private Resource r;
45     Producer(Resource r){
46         this.r = r;
47     }
48     public void run(){
49         while(true){
50             try {
51                 r.set("商品");
52             } catch (InterruptedException e) {
53                 e.printStackTrace();
54             }
55         }
56     }
57 }
58 
59 class Consumer implements Runnable{
60     private Resource r;
61     Consumer(Resource r){
62         this.r = r;
63     }
64     public void run(){
65         while(true){
66             try {
67                 r.out();
68             } catch (InterruptedException e) {
69                 e.printStackTrace();
70             }
71         }
72     }
73 }
74 
75 public class Demo{
76     public static void main(String[] args) {
77         Resource r = new Resource();
78         Thread t1 = new Thread(new Producer(r));
79         Thread t2 = new Thread(new Producer(r));
80         Thread t3 = new Thread(new Consumer(r));
81         Thread t4 = new Thread(new Consumer(r));
82         t1.start();
83         t2.start();
84         t3.start();
85         t4.start();
86     }
87 }

 JDK1.5中提供了多线程升级解决方案。将同步Synchronized替换成Lock操作。将Object中的wait、notify、notifyAll替换成了Condition对象,该对象可以Lock锁进行获取。  

 如何停止线程:stop方法已经过时,只能让run方法结束。开启多线程运行,运行代码通常是循环结构。只要控制住循环,就可以让run方法结束,也就是线程结束。

 特殊情况:当线程处于冻结状态。就不会读取到标记,那么线程就不会结束。当没有指定的方式让冻结的线程恢复到运行状态时,这时需要对冻结进行清除。强制让线程恢复到运行状态中来。这样就可以操作标记让线程结束。

 Thread类提供该方法interrupt();

 1 class StopThread implements Runnable{
 2     private boolean flag = true;
 3     public synchronized void run(){
 4         while(flag){
 5             try{
 6                 wait();
 7             }catch(InterruptedException e){
 8                 System.out.println(Thread.currentThread().getName() + "...exception");
 9             }
10             System.out.println(Thread.currentThread().getName() + "...run");
11         }
12     }
13     public void changeFlag(){
14         flag = false;
15     }
16 }
17 
18 public class Demo{
19     public static void main(String[] args) {
20         StopThread st = new StopThread();
21         Thread t1 = new Thread(st);
22         Thread t2 = new Thread(st);
23         t1.start();
24         t2.start();
25         
26         int num = 0;
27         while(true){
28             if(num++ == 60){
29                 t1.interrupt();
30                 t2.interrupt();
31                 st.changeFlag();
32                 break;
33             }
34             System.out.println(Thread.currentThread().getName() + "....." + num);
35         }
36         System.out.println("over");
37     }
38 }

输出结果:

...
...
main.....59
main.....60
over
Thread-0...exception
Thread-0...run
Thread-1...exception
Thread-1...run

 守护线程:即后台线程。线程对象.setDaemon(true)

 当正在运行的线程都是守护线程时(即前台线程全结束),JVM退出。该方法必须在启动线程前调用。

 Join方法:线程对象.join(),当A线程执行到了B线程的.join()方法,A就会等待。等B线程都执行完,A才会执行。join可以用来临时加入线程执行。

 yield方法:暂停当前正在执行的线程对象,并执行其他线程。

posted @ 2017-01-15 14:23  Chris_z  阅读(189)  评论(0编辑  收藏  举报