多線程

首先理解一下程序、進程、線程的具體解釋
程序(program):是爲完成特定任務、用某種語言編寫的一組指令的集合。即指一段靜態的代碼,靜態對象。
進程(process):是程序的一次執行過程,或是正在運行的一個程序。動態過程:有它自身的產生、存在和消亡的過程。
如:運行中的QQ,運行中的MP3播放器
程序是靜態的,進程是動態的
線程(thread):進程可進一步細化爲線程,是一個程序內部的一條執行路徑
若一個程序可同一時間執行多個線程,就是支持多線程的
廢話不多說;看看我看完視頻後寫的例子
創建線程的第一種方法

package com.ligang.com;

import javax.swing.text.StyledEditorKit.ForegroundAction;
/*
 * 創建線程的第一種方法 繼承Thread類並重寫其中的run()方法
 */
public class ThreadTest {
 public static void main(String[] args) {
    new Thread(){//用內部內實現 重寫run()方法,求1-100的奇數和偶數
        @Override
        public void run() {
            for(int i=0;i<=100;i++){
                if(i%2==0){
                    System.out.println(Thread.currentThread().getName()+"::::"+i+"偶數");
                }//currentThread():表示當前線程 getName():表示當前線程的名字
            }
        }
    }.start();//最後調用start方法

 new Thread(){
     public void run() {
         for(int i=0;i<=100;i++){
             if(i%2!=0){
                 System.out.println(Thread.currentThread().getName()+"::::"+i+"奇數");
            }
         }
     }
 }.start();
 }
}

創建線程的第二種方法並實現瞭如何控制同步進程的第二種方法

package com.ligang.com;

import java.text.BreakIterator;

/*
 * 多線程的第二種方式,實現runnable接口
 * 相比於繼承的方式實現多線程,runnable有可以多實現與共用同一個資源的優點
 * 同步的第二種方式同步塊方法:public void synchronized +方法名{}
 */
class windows implements Runnable{//實現runnable接口
    int x=100;//共享的數據
    public void run() {//重寫run方法
        while(true){
            world();
        }
    }
    public synchronized void world(){//設置進程代碼同步塊:這裏也會調用代碼監視器,
                                                            //只不過他是隱式的調用自己本身的對象作爲代碼監視器

        if (x > 0) {
            try {
                Thread.currentThread().sleep(10);//讓他休息一下
            } catch (InterruptedException e) {
                e.printStackTrace();
            }


            System.out.println(Thread.currentThread().getName() + "還剩票數:" + x--);
        } 

    }
}
public class RunnablTset {
public static void main(String[] args) {
windows w1=new windows();//只需要創建一次線程,接下來便可以多次調用
Thread t1=new Thread(w1);
Thread t2=new Thread(w1);
t1.setName("子線程2:");//設置線程的名字
t2.setName("子線程3:");
t1.start();
t2.start();

}
}

用synchronized的方式來實現代碼的同步

package com.ligang.com;

import java.text.BreakIterator;
/*
 * 定義兩個線程實現兩個窗口同時賣票的模擬
 * 用繼承方式實現的多線程控制其安全性
 * 也是用synchronized的方式來實現代碼的同步,synchronized()中的代碼監視器不能用this了 
 * 因爲繼承的時候創建了三個對象,所以每次都會使用自己的代碼監視器,
 * 從而沒有解決代碼同步的問題
 */

public class ThreadTest2 {
static int x=100;//假設有一百張票,讓兩個線程一起賣這一百張票,所以一定要把票數加static修飾
static Object obj=new Object();//定義一個類似於x似的靜態變量,用於代碼監視器
public static void main(String[] args) {

    new Thread(){//在主函數中定義兩個內部類,實現兩個窗口的模擬
        @Override
        public void run() {//重寫run()方法
            while(true){
            synchronized (obj) {//用synchronized的方式來實現代碼的同步
                if (x > 1) {
                    System.out.println(Thread.currentThread().getName() + "還剩票數:" + x--);//輸出所剩的票數
                } else {
                    break;
                }
            }
        }
            }
    }.start();//調用start()方法開啓線程
    new Thread(){
        @Override
        public void run() {
            while(true){
                synchronized (obj) {//用synchronized的方式來實現代碼的同步
                    if (x > 0) {
                        System.out.println(Thread.currentThread().getName() + "還剩票數:" + x--);
                    } else {
                        break;
                    }
                }
            }
        }
    }.start();
}

}

來舉個小例子

package com.ligang.com;

import java.text.BreakIterator;

/*
 * 銀行有一個賬戶。
*   有兩個儲戶分別向同一個賬戶存3000元,每次存1000,存3次。每次存完打印賬戶餘額。
*加上線程的通信,實現兩用戶交替向銀行卡里存錢
*wait();暫停進程使用
*notify()/notafyAll()喚醒進程
*
 */
public class Desposit implements Runnable {
    double x = 0;

    @Override
    public void run() {
        for (int i = 0; i < 3; i++) {
            synchronized (this) {
                notify();// 喚醒進程
                x = x + 1000;
                System.out.println("當前用戶:" + Thread.currentThread().getName() + "餘額爲:" + x);
                try {
                    wait();// 等待一下 釋放cpu資源
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    public static void main(String[] args) {
        Desposit p = new Desposit();
        Thread p1 = new Thread(p);
        Thread p2 = new Thread(p);
        p1.setName("客戶1");
        p2.setName("客戶2");
        p1.start();
        p2.start();
    }
}

生產者與消費者的經典例題

package com.ligang.com;

import javax.print.attribute.standard.NumberOfInterveningJobs;
import javax.sound.midi.VoiceStatus;


    /*
     * 生產者與消費者的經典例題
     */

    class Clerk {

        int product;

        public synchronized void addProduct() {// 生產
            if (product > 10) {
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } else {
                product++;
                System.out.println(Thread.currentThread().getName()+"生產的第"+product+"個產品");
                notify();
            }
        }

        public synchronized void subProduct() {// 消費
            if (product <0) {
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } else {
                System.out.println(Thread.currentThread().getName()+"消費的第"+product+"個產品");
                product--;
                notify();
            }
        }
    }

    class Produce implements Runnable {// 生產者生產
        Clerk clerk;

        public Produce(Clerk clerk) {
            this.clerk = clerk;
        }

        @Override
        public void run() {
            System.out.println("生產者生產產品");
            while (true) {
                try {
                    Thread.currentThread();
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                clerk.addProduct();
            }
        }
    }
        class Couser implements Runnable {// 消費者消費
            Clerk clerk;

            public Couser(Clerk clerk) {
                this.clerk = clerk;
            }

            @Override
            public void run() {
                System.out.println("消費者消費產品");
                while (true) {
                    try {
                        Thread.currentThread();
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    clerk.subProduct();
                }
            }
        }

    public class ProductTest {
    public static void main(String[] args) {
    Clerk s=new Clerk();
    Produce p1=new Produce(s);
    Couser s1=new Couser(s);
    Thread  t1=new Thread(p1);
    Thread t3=new Thread(p1);
    Thread t4=new Thread(p1);
    Thread t2=new Thread(s1);
    t1.setName("生產者1:");
    t3.setName("生產者2:");
    t4.setName("生產者3:");
    t2.setName("消費者:");
    t1.start();
    t2.start();
    t3。start();
    t4.start();
    }
}

這篇博客中寫的文字很少,我想記得都寫在了代碼的註釋中了,總結起來還是很簡單的 線程的創建我寫了兩種方式,同步我也寫了兩個方式,後面寫了兩個作業題,把前面學的知識總結了一下,,菜鳥敬上,大神們,海涵

發佈了40 篇原創文章 · 獲贊 3 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章