Java -- 線程

線程

  • 線程的三種狀態(tài)(五種狀態(tài))
    1. 運行態(tài)(Running) ---> yield() ---> 就緒態(tài)
    2. 就緒態(tài)(Runnable)
    3. 阻塞態(tài)(Blocked)
      sleep( ) / IO中斷 / join( )
      wait( ) ---> 等待池 ---> notify( ) / notifyAll( ) ---> 等待池
      synchronized ---> 等鎖池 ---> 搶鎖池 ---> 就緒態(tài)
  • Thread類有兩個靜態(tài)方法可以讓正在執(zhí)行的線程放棄對cup的占用
    1.sleep - 讓CPU的時候不考慮優(yōu)先級司浪,yield要考慮優(yōu)先級起暮。
    2.yield - 讓出CPU后進入就緒態(tài)包吝,sleep讓出CPU后進入阻塞態(tài)
public class Frame extends JFrame implements ActionListener{

    private JButton aButton,bButton,cButton,dButton;
    private Thread thread1,thread2;
    public static final int Width = 80;
    public static final int Height = 50;
    
    
    public Frame(){
        this.setSize(500,300);
        this.setResizable(false);
        this.setLocationRelativeTo(null);
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        this.setLayout(null);
        
        
        aButton = new JButton("上傳");
        aButton.setBounds(20, 150, Width, Height);
        
        bButton = new JButton("下載");
        bButton.setBounds(140, 150, Width, Height);
        
        cButton = new JButton("計算");
        cButton.setBounds(260, 150, Width, Height);
        cButton.setEnabled(false);//一開始禁用"計算"按鈕
        
        dButton = new JButton("關(guān)于");
        dButton.setBounds(380, 150, Width, Height);
        
        aButton.addActionListener(this);
        bButton.addActionListener(this);
        cButton.addActionListener(this);
        dButton.addActionListener(this);        
        
        this.add(aButton);
        this.add(bButton);
        this.add(cButton);
        this.add(dButton);
                
    }
    
    private void download(){
        
        try {
            Thread.sleep(6000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    
    private void upload(){
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    
    public static void main(String[] args) {
        new Frame().setVisible(true);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        String command = e.getActionCommand();
        if (command.equals("上傳")) {
            aButton.setEnabled(false);
            aButton.setText("上傳中");
        thread1= new Thread(()->{
                upload();
                aButton.setEnabled(true);
                aButton.setText("上傳");
            });
        thread1.start();
        }
        else if (command.equals("下載")) {
            bButton.setEnabled(false);
            bButton.setText("下載中");
            thread2 = new Thread(new Runnable() {
                
                @Override
                public void run() {
                    download();
                    bButton.setEnabled(true);
                    bButton.setText("下載");                                      
                }
            });
            thread2.start();
        }
        else if (command.equals("計算")) {
            
        }
        else if (command.equals("關(guān)于")) {
            JOptionPane.showMessageDialog(null, "load.....");
        }
        
        new Thread(() -> {
            if (thread1 != null && thread2 != null) {
                try {
                thread1.join();
                thread2.join();
                cButton.setEnabled(true);
                }
                catch (InterruptedException e1) {
                    e1.printStackTrace();
                }
            }           
        }).start();
        
    }
}

線程同步

  • synchronized(隱式鎖機制)有兩種用法:
    1.放在方法的前面,該方法值允許搶占到對象鎖的線程進入執(zhí)行
    2.構(gòu)造synchronized代碼塊(同步代碼塊)始锚,只允許搶占到對象鎖的線程進入執(zhí)行

  • Lock(顯示鎖機制)

private Lock lock = new ReentrantLock();
lock.lock();
.....
lock.unlock();
  • 沒有搶占到對象鎖的線程在系統(tǒng)自動維護的等鎖池中等待
    如果搶到鎖的線程釋放了對象鎖,那么這些等鎖的線程就搶鎖岁诉,誰搶到鎖誰就進入同步代碼塊中執(zhí)行娩贷,沒有搶到的繼續(xù)等待
    基于synchronized關(guān)鍵字的鎖機制是可重入的鎖機制

  • join方法是一個阻塞式方法,表示等待線程結(jié)束
    如果將join方法放到主線程碱茁,會導(dǎo)致其他線程被阻塞

package org.mobiletrain;

//import java.util.ArrayList;
//import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;


//線程同步問題
class BankAccount {

    private double balance;
    private Lock lock = new ReentrantLock();
    
    public double getBalance() {        
        return balance;
    }
    
    //使用Java 5 以后的鎖機制解決同步問題
    public /*synchronized*/ void transfer(double money){
        
        lock.lock();
        System.out.println(Thread.currentThread().getName());
        double newBalance = balance + money;
        try {
            Thread.sleep(1);
        } 
        catch (InterruptedException e) {
        }       
        balance = newBalance;   
        lock.unlock();
    }
} 


class AddMoneyHandler implements Runnable{
    

    private BankAccount account;
    private int money;
    
    public AddMoneyHandler(BankAccount account,int money) {
        this.account = account;
        this.money = money;
    }
    
    @Override
    public void run() {
        //synchronized (account) {
            account.transfer(money);
            
        //}
    }
    
}

public class Test01 {

    public static void main(String[] args) throws InterruptedException {
        //List<Thread> list = new ArrayList<>();
        ExecutorService service = Executors.newFixedThreadPool(10);
        BankAccount mainAccount = new BankAccount();
        for (int i = 0; i < 100; i++){
            service.execute(new AddMoneyHandler(mainAccount, 100));
            //Thread t = new Thread(new AddMoneyHandler(mainAccount, 100));
            //list.add(t);
            //t.start();
        }
        service.shutdown();
        //判斷線程池里的線程有沒有終止
        while ( ! service.isTerminated()) {
    
        }
        //join方法是一個阻塞式方法裸卫,表示等待線程結(jié)束
        //如果將join方法放到主線程,會導(dǎo)致其他線程被阻塞
        //for (Thread thread : list) {
            //線程對象的join()
            //thread.join();
        //}
        System.out.println("賬戶余額:¥" + mainAccount.getBalance());
    }
}

  • wait()是讓線程暫停(進入對象等待池)纽竣,然后釋放對象的鎖 --- 在等待池中的線程需要其他線程將其喚醒

  • 設(shè)置優(yōu)先級改變的是線程獲得CPU調(diào)度的幾率

  • 裝潢模式
    將線程不安全的容器包裝成線程安全的容器

List<String> list = Collections.synchronizedList(new ArrayList<>());
public static void main(String[] args) {
        List<String> list = Collections.synchronizedList(new ArrayList<>());
        //ArrayList是線程不安全的墓贿,因為它的方法沒有加synchronized保護
        //List<String> list = new ArrayList<>();
        ExecutorService service = Executors.newFixedThreadPool(5);
        
        for (int i = 0; i < 5; i++){
            service.execute(new Runnable() {
                
                @Override
                public void run() {                 
                    for (int j = 0; j < 100000; j++){                       
                    list.add("Hello");                                  
                    }                       
                }
            });
        }
        service.shutdown();
        while (! service.isTerminated()){           
        }
        System.out.println(list.size());
    }       
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末茧泪,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子聋袋,更是在濱河造成了極大的恐慌队伟,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件幽勒,死亡現(xiàn)場離奇詭異缰泡,居然都是意外死亡,警方通過查閱死者的電腦和手機代嗤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進店門棘钞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人干毅,你說我怎么就攤上這事宜猜。” “怎么了硝逢?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵姨拥,是天一觀的道長。 經(jīng)常有香客問我渠鸽,道長叫乌,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任徽缚,我火速辦了婚禮憨奸,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘凿试。我一直安慰自己排宰,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布那婉。 她就那樣靜靜地躺著板甘,像睡著了一般。 火紅的嫁衣襯著肌膚如雪详炬。 梳的紋絲不亂的頭發(fā)上盐类,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天,我揣著相機與錄音呛谜,去河邊找鬼在跳。 笑死,一個胖子當(dāng)著我的面吹牛呻率,可吹牛的內(nèi)容都是我干的硬毕。 我是一名探鬼主播,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼礼仗,長吁一口氣:“原來是場噩夢啊……” “哼吐咳!你這毒婦竟也來了逻悠?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤韭脊,失蹤者是張志新(化名)和其女友劉穎童谒,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體沪羔,經(jīng)...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡饥伊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了蔫饰。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片琅豆。...
    茶點故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖篓吁,靈堂內(nèi)的尸體忽然破棺而出茫因,到底是詐尸還是另有隱情,我是刑警寧澤杖剪,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布冻押,位于F島的核電站,受9級特大地震影響盛嘿,放射性物質(zhì)發(fā)生泄漏洛巢。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一次兆、第九天 我趴在偏房一處隱蔽的房頂上張望稿茉。 院中可真熱鬧,春花似錦类垦、人聲如沸狈邑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至糕伐,卻和暖如春砰琢,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背良瞧。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工陪汽, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人褥蚯。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓挚冤,卻偏偏與公主長得像,于是被迫代替她去往敵國和親赞庶。 傳聞我的和親對象是個殘疾皇子训挡,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,828評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 下面是我自己收集整理的Java線程相關(guān)的面試題澳骤,可以用它來好好準(zhǔn)備面試。 參考文檔:-《Java核心技術(shù) 卷一》-...
    阿呆變Geek閱讀 14,738評論 14 507
  • 不管你是新程序員還是老手澜薄,你一定在面試中遇到過有關(guān)線程的問題为肮。Java語言一個重要的特點就是內(nèi)置了對并發(fā)的支持,讓...
    堯淳閱讀 1,588評論 0 25
  • 該文章轉(zhuǎn)自:http://blog.csdn.net/evankaka/article/details/44153...
    加來依藍閱讀 7,333評論 3 87
  • 下面是Java線程相關(guān)的熱門面試題肤京,你可以用它來好好準(zhǔn)備面試颊艳。 http://blog.csdn.net/u010...
    MrWang915閱讀 513評論 0 4
  • 世間萬物,文學(xué)忘分,美食棋枕,書法,朗讀妒峦,畫畫戒悠,音樂,地理等等舟山,能讓人一見鐘情的只有那么幾件绸狐,比如,我看到宋詞累盗,“...
    樂小初閱讀 253評論 0 0