JAVA多線程 & 同步關鍵詞synchronized & ReadWriteLock讀寫文件


  在java中可有兩種方式實現多線程,一種是繼承Thread類,一種是實現Runnable接口;Thread類是在java.lang包中定義的。一個類只要繼承了Thread類同時覆寫了本類中的run()方法就可以實現多線程操作了,但是一個類只能繼承一個父類,這是此方法的局限。

1 public class Actor extends Thread  {
2     public void run(){
3          //線程執行的操作
4         }
5 }   

  在實際開發中一個多線程的操作很少使用Thread類,而是通過Runnable接口完成。

1 public class Actress implements Runnable{
2 
3     @Override
4     public void run() {
5         //線程執行的操作
6         }
7 }    

  在主方法中調用這兩種線程。

1     public static void main(String[] args) {
2         Thread actor=new Actor();
3         actor.setName("Mr.thread");  //Thread 線程
4         actor.start();
5         
6         Thread actressThread=new Thread(new Actress(),"Miss.Runnable");  //Runnable 線程
7         actressThread.start();
8     }

 

兩種實現方式的區別和聯系:

  在程序開發中只要是多線程肯定永遠以實現Runnable接口為主,因為實現Runnable接口相比繼承Thread類有如下好處:

    1、避免點繼承的局限,一個類可以繼承多個接口。

    2、適合於資源的共享

  以賣票程序為例,通過Thread類完成:

 1 package multithreading;
 2 
 3 public class MyThreadWithExtends extends Thread {
 4 
 5     private int tickets = 10;
 6 
 7     @Override
 8     public void run() {
 9 
10         for (int i = 0; i <= 100; i++) {
11             if(tickets>0){
12                 System.out.println(Thread.currentThread().getName()+"--賣出票:" + tickets--);
13             }
14         }
15     }
16     
17     
18     public static void main(String[] args) {
19         MyThreadWithExtends thread1 = new MyThreadWithExtends();
20         MyThreadWithExtends thread2 = new MyThreadWithExtends();
21         MyThreadWithExtends thread3 = new MyThreadWithExtends();
22 
23         thread1.start();
24         thread2.start();
25         thread3.start();
26         
27         //每個線程都獨立,不共享資源,每個線程都賣出了10張票,總共賣出了30張。如果真賣票,就有問題了。
28     }
29 
30 }

運行結果:

  Thread-0--賣出票:10
  Thread-2--賣出票:10
  Thread-1--賣出票:10
  Thread-2--賣出票:9
  Thread-0--賣出票:9
  Thread-2--賣出票:8
  Thread-1--賣出票:9
  Thread-2--賣出票:7
  Thread-0--賣出票:8
  Thread-2--賣出票:6
  Thread-2--賣出票:5
  Thread-2--賣出票:4
  Thread-1--賣出票:8
  Thread-2--賣出票:3
  Thread-0--賣出票:7
  Thread-2--賣出票:2
  Thread-2--賣出票:1
  Thread-1--賣出票:7
  Thread-0--賣出票:6
  Thread-1--賣出票:6
  Thread-0--賣出票:5
  Thread-0--賣出票:4
  Thread-1--賣出票:5
  Thread-0--賣出票:3
  Thread-1--賣出票:4
  Thread-1--賣出票:3
  Thread-1--賣出票:2
  Thread-0--賣出票:2
  Thread-1--賣出票:1
  Thread-0--賣出票:1

 

  如果用Runnable就可以實現資源共享,下面看例子:

 1 package multithreading;
 2 
 3 public class MyThreadWithImplements implements Runnable {
 4 
 5     private int tickets = 10;
 6 
 7     @Override
 8     public void run() {
 9 
10         for (int i = 0; i <= 100; i++) {
11             if(tickets>0){
12                 System.out.println(Thread.currentThread().getName()+"--賣出票:" + tickets--);
13             }
14         }
15     }
16     
17     
18     public static void main(String[] args) {
19         MyThreadWithImplements myRunnable = new MyThreadWithImplements();
20         Thread thread1 = new Thread(myRunnable, "窗口一");
21         Thread thread2 = new Thread(myRunnable, "窗口二");
22         Thread thread3 = new Thread(myRunnable, "窗口三");
23 
24         thread1.start();
25         thread2.start();
26         thread3.start();
27     }
28 
29 }

運行結果:

  窗口二--賣出票:10
  窗口三--賣出票:9
  窗口一--賣出票:8
  窗口三--賣出票:6
  窗口三--賣出票:4
  窗口三--賣出票:3
  窗口三--賣出票:2
  窗口三--賣出票:1
  窗口二--賣出票:7
  窗口一--賣出票:5

每個線程共享了對象myRunnable的資源,賣出的總票數是對的,但是順序是亂的,怎么辦?

 

同步關鍵詞synchronized

 

線程執行的時候,一個個執行不就有序了。即線程1在執行的時候,其他線程阻塞不要執行。

加synchronize。

 1 package multithreading.sync;
 2 
 3 public class MyThreadWithImplements implements Runnable {
 4 
 5     private int tickets = 10;
 6 
 7     @Override
 8     public synchronized void run() {
 9             //同步關鍵詞synchronized
10         for (int i = 0; i <= 100; i++) {
11             if(tickets>0){
12                 System.out.println(Thread.currentThread().getName()+"--賣出票:" + tickets--);
13             }
14         }
15     }
16     
17     
18     public static void main(String[] args) {
19         
20         MyThreadWithImplements myRunnable = new MyThreadWithImplements();
21         Thread thread1 = new Thread(myRunnable, "窗口一");
22         Thread thread2 = new Thread(myRunnable, "窗口二");
23         Thread thread3 = new Thread(myRunnable, "窗口三");
24 
25         thread1.start();
26         thread2.start();
27         thread3.start();
28     }
29 
30 }

運行結果

  窗口一--賣出票:10
  窗口一--賣出票:9
  窗口一--賣出票:8
  窗口一--賣出票:7
  窗口一--賣出票:6
  窗口一--賣出票:5
  窗口一--賣出票:4
  窗口一--賣出票:3
  窗口一--賣出票:2
  窗口一--賣出票:1

 

缺陷

  1、如果這個獲取鎖的線程由於要等待IO或者其他原因(比如調用sleep方法)被阻塞了,但是又沒有釋放鎖,其他線程便只能干巴巴地等待,這多么影響程序執行效率。


  2、當有多個線程讀寫文件時,讀寫操作會發生沖突現象,寫操作會發生沖突現象,但是讀操作不會發生沖突現象。但是采用synchronized關鍵字來實現同步的話,就會導致一個問題:如果多個線程都只是進行讀操作,當一個線程在進行讀操作時,其他線程只能等待無法進行讀操作。


  因此就需要一種機制來使得多個線程都只是進行讀操作時,線程之間不會發生沖突,通過Lock就可以辦到。另外,通過Lock可以知道線程有沒有成功獲取到鎖。這個是synchronized無法辦到的。總的來說,也就是說Lock提供了比synchronized更多的功能。

ReadWriteLock讀寫文件

概述

ReadWriteLock是一個接口,在它里面只定義了兩個方法:一個讀的鎖和一個寫的鎖。

讀的鎖:A線程獲取了讀的鎖,那么B線程也可以獲取讀的鎖。

寫的鎖:A線程獲取了寫的鎖,那么B線程不能獲取讀也不能獲取寫的鎖。

 1 public interface ReadWriteLock {  
 2     /** 
 3      * Returns the lock used for reading. 
 4      * 讀的鎖,A線程獲取了讀的鎖,那么B線程也可以獲取讀的鎖 
 5      * @return the lock used for reading. 
 6      */  
 7     Lock readLock();  
 8    
 9     /** 
10      * Returns the lock used for writing. 
11      * 寫的鎖,A線程獲取了寫的鎖,那么B線程不能獲取讀也不能獲取寫的鎖。 
12      * @return the lock used for writing. 
13      */  
14     Lock writeLock();  
15 } 

。。。未完待續

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM