天天看點

java 多線程

線程的概念:

在一個程式中同時獨立運作的多個獨立流程,每一個獨立流程就是一個線程

線程的三要素:

CPU,Code,Data

程序:完成一個任務的過程

一個程序包括多個線程

線程是計算機執行的最小程式單元

線程并發

線程的開發:繼承Thread類與實作Runnable接口2種方式

1.繼承Thread類:

<b>public</b> <b>class</b> MyThread1 <b>extends</b> Thread {

       <b>public</b> <b>void</b> run(){

             <b>for</b>(<b>int</b> i=0;i&lt;60;i++){

                  System. out.println("####" +i);

            }

      }

}

<b>public</b> <b>class</b> MyThread2 <b>extends</b> Thread{

                  System. out.println("$$$$" +i);

<b>public</b> <b>class</b> TestThread01 {

       <b>public</b> <b>static</b> <b>void</b> main(String[] args) {

            Thread t1= <b>new</b> MyThread1();

            Thread t2= <b>new</b> MyThread2();

            t1.start();

            t2.start();

2.實作Runnable接口:

  使用者開發一個類實作Ruannable接口

  實作run()方法

  運作線程

Ruannable target=new MyRunnable2();

Thread t3=new Thread(target);

<b>public</b> <b>class</b> MyThread03 <b>implements</b> Runnable{

       <b>public</b> <b>void</b> run() {

             <b>for</b>(<b>int</b> i=0;i&lt;400;i++){

                  System. out.println("****" +i);

<b>public</b> <b>class</b> MyThread04 <b>implements</b> Runnable{

                  System. out.println("&amp;&amp;&amp;&amp;" +i);

<b>public</b> <b>class</b> TestThread3 {

            Runnable runn3=<b>new</b> MyThread03();

            Runnable runn4= <b>new</b> MyThread04();

            Thread t3= <b>new</b> Thread(runn3);

            Thread t4= <b>new</b> Thread(runn4);

            t3.start();

            t4.start();

繼承Thread是面向對象的程式設計方式

實作Runnable接口解決了單一繼承限制

線程的狀态:

初始狀态

Thread a=new Thread();

可運作狀态

a.start(),但此時未獲得CPU或者可運作狀态CPU時間片到期

運作狀态

可運作狀态獲得CPU

終結狀态

run()方法退出

sleep()方法

public static void sleep(long millis) throws InterruptedException

             <b>for</b>(<b>int</b> i=0;i&lt;10;i++){

                   <b>try</b> {

                        Thread. sleep(200);

                  } <b>catch</b> (InterruptedException e) {

                  }

運作結果:

$$$$0

####0

####1

$$$$1

$$$$2

####2

$$$$3

####3

####4

$$$$4

$$$$5

####5

$$$$6

####6

####7

$$$$7

####8

$$$$8

$$$$9

####9

join()方法:

  join()方法也會導緻線程的阻塞

  特點:如果目前線程中調用了另外一個線程join方法,

join()方法的問題:

  如果兩個線程彼此調用對方的join方法,會導緻程式無法運作

  解決方法如下:

    public final void join(long millis) throws InterruptedException

      Thread t;

             <b>for</b>(<b>int</b> i=0;i&lt;100;i++){

                         t.join(200);

                        e.printStackTrace();

線程同步:

多個線程并發通路同一個對象,如果破壞了不可分割的操作,進而就會造成資料不一緻。

臨界資源:多個線程并發通路同一個對象

原子操作:不可分割的操作

被多線程并發通路時,如果一個對象有可能出現資料不一緻的問題,那麼這個對象就稱為線程不安全的對象

如何解決多線程并發通路的問題

synchronized(object){

或者寫成synchronized(this){}

synchronized修飾方法

public  synchronized void push(){}

死鎖:

用于解決死鎖的方法:wait()與notify()方法(這兩種方法也可進行線程間的通信)

生産者與消費者問題:

     同時兩個線程操作一個棧,一個線程負責往棧中添加元素,一個線程負責删除棧中元素。

5.生産者與消費者問題

  1.建立臨界資源(Stack) push(),pop(),print()

  2.給push()與pop()方法加上線程同步

  3.定義一個線程類,實作往Stack對象中存放那個相應資料,線上程中初始化臨界資源(Stack)

  4.定義一個線程類,實作從Stack中取出相應資料,線上程中初始化臨界資源(Stack)

  5.寫一個測試類,啟動3,4中建立的線程

  6.運作5中的測試類進行測試,發現出現異常,分析異常,解決異常

    異常原因:存資料時,字元數組大小固定導緻異常

              取資料時,字元數組下标越界導緻異常

  7.解決異常:在一中建立的臨界資源(Stack)中的push()方法中加入判斷,如果目前下标值==數組長度,則不能繼續存入資料,此時,通過線程的wait()方法,通知消費者從臨界資源讀取資料;

              在一中建立的臨界資源(Stack)中的pop()方法中加入判斷,如果目前下标值==0,則不能繼續取出資料,此時,通過線程的notify()方法,通知生産者向臨界資源中存入資料

              當生産者往臨界資源中存入資料時,需要通知消費者從臨界資源中讀取資料;

              當消費者從臨界資源中取出資料時,需要通知生産者向臨界資源中存入資料;

//臨界資源

public class ProducerStack {

private char[] data=new char[12];

private int index=0;

public synchronized void push(char ch){

while(data.length==index){

try {

this.wait();

} catch (InterruptedException e) {

e.printStackTrace();

data[index]=ch;

/* try {

Thread.sleep(100);

}*/

index++;

this.notify();

System.out.println(ch+" push Stack:");

public synchronized void pop(String s){

System.out.println(s);

while(index==0){

index--;

System.out.println(data[index]+" pop Stack");

data[index]=' ';

public void print(String s){

for(int i=0;i&lt;data.length;i++){

System.out.print(data[i]);

System.out.println();

//消費者

public class Consumer extends Thread {

 ProducerStack ps;

 public Consumer(ProducerStack ps) {

  this.ps=ps;

 }

 public void run() {

  ps.pop("pop01-----");

  ps.print("pop-------");

//生産者

public class Producer extends Thread {

 public Producer(ProducerStack ps) {

  for(int i=0;i&lt;20;i++){

   ps.push('s');

   }

  ps.print("push----");

//測試類

public class TestProducer {

 public static void main(String[] args) {

  ProducerStack ps=new ProducerStack();

  Thread p=new Producer(ps);

  Thread con=new Consumer(ps);

  p.start();

  con.start();

上一篇: Java多線程
下一篇: Java多線程

繼續閱讀