Thread-概念和實例

概念

一、線程:Thread

進程:    正在進行的程序,是系統進行資源分配和調度的一個獨立單位,擁有獨立的內存空間和系統資源
多進程:  多個程序在運行

線程:    就是進程中一個負責程序執行的控制單元。
多線程:  一個進程中可以有多個執行路徑 稱爲多線程。多線程就是最大化的提高CPU的利用率,它可與同屬一個進程的其他的線程共享進程所擁有的
    全部資源.

其他:一個進程當中至少要有一個線程。
開啓多個線程,是爲了同時運行多個任務
每一個線程都有自己運行的內容,這個內容可以稱爲線程要執行的任務

二、創建線程

    線程執行需要擁有CPU,如果線程未獲得CPU則該線程處於等待狀態

    1.繼承: Thread
    2.重寫:run
    3.創建線程對象
    4.啓動:start()-->其實就是執行run方法,
但是不一定會立馬執行,只有等當前線程獲得CPU執行權纔會真正執行

通過實現接口創建線程
1.實現接口:java.lang.Runnable
2.重寫方法:run
3.創建線程對象:
Thread t = new Thread(實現接口的對象)
4.啓動線程:start()


三、線程的生命週期

        新生狀態:線程對象被創建出來
    可運行狀態:線程處理裝備轉換,只是缺少CPU執行權
        start()
    運行運行狀態:
    阻塞狀態:線程處於等待狀態,並且釋放CPU執行權
        sleep():等待狀態,並且釋放CPU執行權
        wait():等待狀態,擁有CPU執行權

    死亡狀態:線程結束
        stop()
        run方法執行結束

四、同步:多線程訪問同一份資源所產生的衝突

synchronized
1.代碼塊
任何一對象都有鎖功能
synchronized(鎖對象){
//執行的代碼
}

2.方法:在方法前加synchronized
a.非靜態方法的鎖對象是當前類對象
b.靜態方法的鎖對象是當前字節碼文件對象


五、線程同步的面試題

    StringBuilder:非線程安全
    StringBuffer:線程安全

    ArrayList:非線程安全
    Vector:線程安全

    HashMap:非線程安全
    Hashtable:線程安全

實例

sleep阻斷

package com.ibeifeng;

public class Demo {
    public static void main(String[] args) {
        InterruptThread1 it = new InterruptThread1();
        it.start();//it線程啓動,會被阻塞100秒,然後運行
        it.interrupt();//調用中斷方法,會結束阻塞狀態,拋出中斷異常
    }
}

class InterruptThread1 extends Thread {

    public InterruptThread1() {}

    @Override
    public void run() {
        try {
            System.out.println("線程"+getName()+"準備睡20秒,再運行");
            sleep(20000);
        } catch (InterruptedException e) {
            System.err.println("阻塞狀態,中斷信號");
        }
        for(int i=0; i<100; i++) {
            System.out.println(getName()+"正在運行中。。。");
        }
    }
}

設置優先級

package com.ibeifeng;

public class PriorityDemo {
    public static void main(String[] args) {
        MyThread mt1 = new MyThread("aaa");
        MyThread mt2 = new MyThread("bbb");
        MyThread mt3 = new MyThread("ccc");

        //設置優先級
        mt1.setPriority(Thread.MAX_PRIORITY);
        mt2.setPriority(Thread.MIN_PRIORITY);
        mt3.setPriority(Thread.NORM_PRIORITY);

        mt1.start();//注意和run()的區別
        mt2.start();
        mt3.start();
    }

}
//1繼承Thread
class MyThread extends Thread {
    public MyThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        for(int i=0; i<10; i++) {
            try {
                sleep(2000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println(getName()+":,"+getPriority()+","+i);
        }
    }
}

join

package com.ibeifeng;

public class JoinDemo {
    public static void main(String[] args) {
        JoinThread jt = new JoinThread();
        //創建3條線程
        Thread t1 = new Thread(jt);
        Thread t2 = new Thread(jt);
        Thread t3 = new Thread(jt);


        //運行
        t1.start();
        //join方法
        try {
            t1.join();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        t2.start();
        t3.start();
    }
}

class JoinThread implements Runnable {

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName()+":"+i);
        }
    }

}

中斷方法

package com.ibeifeng;

public class InterruptDemo {
    public static void main(String[] args) {
        InterruptThread it = new InterruptThread("旺財");
        it.start();
        //調用中斷方法
        it.interrupt();
    }
}

class InterruptThread extends Thread {
    public InterruptThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        System.out.println("休息100秒");
        try {
            sleep(100000);
        } catch (InterruptedException e) {
            System.err.println("拋出終端異常");
        }

        for(int i=0; i<10; i++) {
            System.out.println();
        }
    }
}

客戶端服務器交互

客戶端

package com.ibeifeng3;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;


public class ClientDemo {
    public static void main(String[] args) {
        try {
            test1();
        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    //循環向服務端發送消息
    public static void test1() throws UnknownHostException, IOException {
        //創建客戶端socket對象
        Socket socket = new Socket("localhost",10086);
        //獲取鍵盤輸入
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        //獲取向服務器的寫入流
        OutputStream os = socket.getOutputStream();
        BufferedWriter bw = new BufferedWriter(
                new OutputStreamWriter(os));
        //鍵盤輸入字符串,寫到服務器
        while(true) {
            System.out.println("請輸入一個字符串");
            String str = br.readLine();
            System.out.println(str);
            //退出條件,輸入“再見”
            if(str!=null&&str.equals("再見")) {
                break;
            }
            bw.write(str);
            bw.newLine();
            bw.flush();
        }

        //3關閉資源
        socket.close();

    }
    public static void test() throws UnknownHostException, IOException {
        //創建客戶端socket對象
        Socket socket = new Socket("localhost",10086);
        //獲取向服務器的寫入流
        OutputStream os = socket.getOutputStream();
        BufferedWriter bw = new BufferedWriter(
                new OutputStreamWriter(os));
        bw.write("你好嗎,你吃了嗎");
        bw.flush();
        //3關閉資源
        socket.close();

    }
}

服務端

package com.ibeifeng3;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

//字符流給服務器發送消息
public class ServerDemo {
    public static void main(String[] args) {
        try {
            test1();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    //循環讀取客戶端的消息
    public static void test1() throws IOException {
        //1 創建一個服務端的Socket對象
        ServerSocket server = new ServerSocket(10086);
        System.out.println("服務器啓動");
        //2 監聽客戶端的連接 
        Socket socket = server.accept();
        //3 建立客戶端的輸入通道
        InputStream  is = socket.getInputStream();
        BufferedReader br = new BufferedReader(new InputStreamReader(is));
        String line = null;
        while((line=br.readLine())!=null) {
            System.out.println(line);
        }
        //4 釋放相關的資源
//      is.close();
        socket.close();
    }
    public static void test() throws IOException {
        //1 創建一個服務端的Socket對象
        ServerSocket server = new ServerSocket(10086);
        System.out.println("服務器啓動");
        //2 監聽客戶端的連接 
        Socket socket = server.accept();
        //3 建立客戶端的輸入通道
        InputStream  is = socket.getInputStream();
        BufferedReader br = new BufferedReader(new InputStreamReader(is));
        System.out.println(br.readLine());//顯示客戶端發送的內容
        //4 釋放相關的資源
//      is.close();
        socket.close();
    }
}

簡易版服務器交互

服務端

package com.ibeifeng2;

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

//網絡通信,  --->ip ,---->端口    (前1024不要使用)
public class ServerDemo {
    public static void main(String[] args) {
        try {
            test();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    public static void test() throws IOException {
        //1 服務端的socket對象
        ServerSocket server = new ServerSocket(12345);
        System.out.println("服務器啓動");

        //2 監聽12345端口,接受客戶端的連接
        Socket socket =  server.accept();//阻塞
        //3 建立客戶端的寫入通道
        InputStream is  = socket.getInputStream();
        byte[] byts = new byte[1024];
        is.read(byts);
        System.out.println(new String(byts));

        //4 關閉資源
        socket.close();

    }
}

客戶端

package com.ibeifeng2;

import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class ClientDemo {
    public static void main(String[] args) {
        try {
            test();
        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    private static void test() throws UnknownHostException, IOException {
        // 1 創建客戶端的 socket對象
        Socket socket = new Socket("localhost", 12345); 

        // 2 獲取寫入流對象
        OutputStream fos = socket.getOutputStream();
        fos.write("你喫飯了嗎".getBytes());

        // 關閉資源
        fos.close();
        socket.close();
    }
}

同步異步

同步1

package com.ibeifeng1;
//異步產生的問題
public class AsyncronizeDemo {
    //取款    --存款1百萬,主卡副卡分別取錢,每次各取1萬,取完爲止
    public static void main(String[] args) {
         //創建兩個線程分別模擬主卡、副卡
        DrawMoneyThread mainCard = new DrawMoneyThread("主卡");
        DrawMoneyThread secondCard = new DrawMoneyThread("副卡");
        mainCard.start();
        secondCard.start();
    }
}
class DrawMoneyThread extends Thread {

    public DrawMoneyThread(String name) {
        super(name);
    }

    static int deposit = 100;//存款100萬
    int money;
    @Override
    public void run() {
        while(deposit>0) {
            deposit--;
            money++;
            System.out.println(getName()+"取款1萬,"+"剩餘"+deposit);
        }
    }
}

同步2

package com.ibeifeng1;
//解決賣票的問題, 使用同步

//模擬賣票窗口,同時賣票,出現重票,負票
public class AsyncronizeDemo1 {
    public static void main(String[] args) {
        SellTicket st1 = new SellTicket("窗口1");
        SellTicket st2 = new SellTicket("窗口2");
        SellTicket st3 = new SellTicket("窗口3");
        st1.start();
        st2.start();
        st3.start();

    }
}

class SellTicket extends Thread {
    static int tickets = 100;

    public SellTicket(String name) {
        super(name);
    }
    @Override
    public void run() {

        while(true) {

            System.out.println(getName()+" 賣出第"+tickets+"張票");
            tickets--;
            if(tickets<=0) {
                break;
            }
        }
    }
}

同步3

package com.ibeifeng1;

//同步代碼,使用Synchronized關鍵字解決同步問題

public class SynchronizedDemo {
    public static void main(String[] args) {
        SellTicket1 st = new SellTicket1("1窗口");
        SellTicket1 st1 = new SellTicket1("2窗口");
        st.start();
        st1.start();
    }
}

class SellTicket1 extends Thread {
    static int tickets = 100;
    private static Object obj = new Object();

    public SellTicket1(String name) {
        super(name);
    }

    @Override
    public void run() {
        boolean flag = true;
        while (flag) {
            flag = sellTickets_static();
        }
    }
    //靜態同步方法  ----  》靜態方法的鎖對象是  類相關信息的對象,理解爲字節碼文件
    private static synchronized boolean sellTickets_static() {
        if (tickets > 0) {
            System.out.println(Thread.currentThread().getName() + " 賣出第" + tickets + "張票");
            tickets--;
        } 
        if(tickets<=0) {
            return false;
        }
        return true;
    }
    //非靜態同步方法  ----  》非靜態方法的鎖對象是 this,也即  當前對象
    private synchronized boolean sellTickets() {
        if (tickets > 0) {
            System.out.println(getName() + " 賣出第" + tickets + "張票");
            tickets--;
        } 
        if(tickets<=0) {
            return false;
        }
        return true;
    }

}

使用Synchronized關鍵字解決同步問題

package com.ibeifeng1;

//同步代碼,使用Synchronized關鍵字解決同步問題

public class SynchronizedDemo1 {
    public static void main(String[] args) {
        SellTicket4 st = new SellTicket4("1窗口");
        SellTicket4 st1 = new SellTicket4("2窗口");
        st.start();
        st1.start();
    }
}

class SellTicket4 extends Thread {
    static int tickets = 100;
    private static Object obj = new Object();

    public SellTicket4(String name) {
        super(name);
    }
    @Override
    public void run() {
        boolean flag = true;
        while (flag) {
            // 傳一個對象,作爲鎖對象
            synchronized (obj) { //SellTicket4.class
                if (tickets > 0) {
                    System.out.println(getName() + " 賣出第" + tickets + "張票");
                    tickets--;
                }
            }
            if(tickets<=0) {
                flag = false;
            }
        }
    }
}

同步5

package com.ibeifeng1;

public class SynchronizedDemo2 {
    public static void main(String[] args) {
        SellTicket3 st = new SellTicket3();

        Thread t = new Thread(st);
        Thread t1 = new Thread(st);

        t.start();
        t1.start();
    }
}


class SellTicket3 implements Runnable {
    static int tickets = 100;

    @Override
    public void run() {
        boolean flag = true;
        while (flag) {
            flag = sellTickets();
        }
    }

    //非靜態同步方法  ----  》非靜態方法的鎖對象是 this,也即  當前對象
    private synchronized boolean sellTickets() {
        if (tickets > 0) {
            System.out.println(Thread.currentThread().getName() + " 賣出第" + tickets + "張票");
            tickets--;
        } 
        if(tickets<=0) {
            return false;
        }
        return true;
    }

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章