1. 程式人生 > >【執行緒】- 4種執行緒通訊方式

【執行緒】- 4種執行緒通訊方式

浪費了“黃金五年”的Java程式設計師,還有救嗎? >>>   

suspend、resume、stop

  • suspend:執行緒掛起:阻塞,但是不會釋放持有資源,包含鎖資源(過期)
  • resume:恢復執行緒執行:掛起-->就緒
  • stop: 暴力終止執行緒

終止執行緒優雅做法,設定執行緒執行的開關

volatile 保證資料的可見性,執行緒執行時每次都會從公共記憶體載入on資料

Thread.currentThread().isInterrupted(): 判斷執行緒是否被中斷:interrupted()

private static class Runner implements Runnable {
    private long i;
    private volatile boolean on = true;
    [@Override](https://my.oschina.net/u/1162528)
    public void run() {
        while (on && !Thread.currentThread().isInterrupted()){
            i++;
        }
        System.out.println("Count i = " + i);
    }
    public void cancel() {
        on = false;
    }
}

缺點:

  1. 獨佔,suspend方法是執行緒作用的公共同步物件的鎖不會被釋放,造成其他執行緒無法訪問公共同步物件

  2. 資料不一致:例如物件屬性賦值時中間掛起執行執行緒,導致整個執行緒的關聯的物件屬性賦值執行過程不完整,造成資料不一致的情況

  • 測試程式碼
package com.zhiwei.thread;

public class ThreadSuspend {

	@SuppressWarnings("deprecation")
	public static void main(String[] args) throws InterruptedException {
		
		SuspendThread suspendThread = new SuspendThread();
		suspendThread.start();
		
		Thread.sleep(5000);
		
		System.out.println("執行緒第1次被掛起-------------------");
		suspendThread.suspend();
		
		System.out.println("執行緒第1次恢復執行-------------------");
		suspendThread.resume();
		
		Thread.sleep(5000);
		
		System.out.println("執行緒第2次被掛起-------------------");
		suspendThread.suspend();
	}
	
}

class SuspendThread extends Thread{
	
	private long i = 0;
	
	public long get(){
		return i;
	}
	
	public void set(long i){
		this.i = i;
	}
	
	@Override
	public void run() {
		while(true){
			System.out.println("i:"+i);
			try {
				Thread.sleep(1000);
				i++;
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	
}

效果:


wait、notify

wait:當前訪問物件的執行緒被阻塞,並且放棄之前擁有的資源,直到被notify/notifyAll方法喚醒,在原來中斷的地方繼續執行

擴充套件:執行緒從原來中斷的地方繼續執行的原因:作業系統是統一管理所有的軟硬體資源的軟體,程序是程式分配資源的單位,執行緒則是程序進行資源進一步劃分的最小的分配資源單位,當執行緒或程序被中斷的時候,作業系統會自動將當前執行緒/程序的狀態存入執行緒控制塊(TCB)和程序控制塊(PCB),然後阻塞當前執行的執行緒/程序,當執行緒/程序達到執行的條件,作業系統會從之前儲存的TCB/PCB中讀取資訊,恢復中斷前的狀態,所以執行緒/程序就成從中斷的地方繼續執行

notify: 喚醒訪問目標物件的1個阻塞執行緒,執行緒進入就緒狀態,分配CPU資源即可執行

注意:如果存在多個執行緒訪問同一個物件,notify喚醒的執行緒是隨機的,notifyAll可以喚醒所有的阻塞執行緒

測試案例:

package com.zhiwei.thread;

public class WaitAndNotify {
	
   private static Object object = new Object();
   
	public static void main(String[] args) throws InterruptedException{
	  threadWait tw = new threadWait();
      threadNotify tn = new threadNotify();
      Thread th1 = new Thread(tw);
      Thread th2 = new Thread(tn);
      th1.start();
      th2.start();
	}
	
	
	private static class threadWait implements Runnable{
		@Override
		public void run() {
			synchronized (object) { 
				try {
					System.out.println(Thread.currentThread().getName() + ":object物件鎖釋放前!");
					object.wait();  
			System.out.println(Thread.currentThread().getName() + ":object物件鎖釋放後!"); 
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	private static class threadNotify implements Runnable{

		@Override
		public void run() {
			synchronized (object) {
				try {
					System.out.println(Thread.currentThread().getName()+":object物件鎖獲取前!");
					object.notify(); 
					System.out.println(Thread.currentThread().getName()+":object物件鎖獲取後!(JVM決定喚醒另外執行緒)");
				} catch (Exception e) {
					e.printStackTrace();
				}
			}		
		}
	}
}

結果:

Thread-0: object物件鎖釋放前!
Thread-1:object物件鎖獲取前!
Thread-1: object物件鎖獲取後!(JVM決定喚醒另外執行緒)
Thread-0:object物件鎖釋放後!

分析:

  1. 執行緒threadWait執行時synchronized (object)的原因,執行緒threadNotify執行緒阻塞,等待threadWait釋放物件鎖才可以執行

  2. 當threadWait執行到 object.wait()時,threadWait執行緒被手動阻塞中斷,釋放物件鎖,因此控制檯只會輸出之前的

“Thread-0:object物件鎖釋放前!”
  1. 因threadWait釋放物件鎖,執行緒threadNotify執行,當執行object.notify(); 時,因object只有1個阻塞執行緒,因此threadWait執行緒被喚醒,但是由於threadNotify還在執行同步程式碼塊,因此執行緒threadWait進入阻塞狀態,當執行緒threadNotify執行完成同步程式碼塊,控制檯輸出
"Thread-1:object物件鎖獲取前!
Thread-1:object物件鎖獲取後!(JVM決定喚醒另外執行緒)"
  1. threadNotify持有的object物件鎖釋放,threadWait獲取物件鎖繼續執行,控制檯輸出
"Thread-0:object物件鎖釋放後!"

await、signal

await和signal類似wait和notify的關係,await會阻塞當前執行緒,直到接收到signal後喚醒繼續執行,這也是執行緒的一種通訊機制

需求:多執行緒交替列印字元

測試程式碼

package com.zhiwei.thread;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class TheadAwait {

	public boolean flag = true;
	Lock lock = new ReentrantLock();
	Condition condition = lock.newCondition();

	public void get() {
		try {
			Thread.sleep(5000);
			lock.lock();
			while (!flag) {
				condition.await();
			}
			System.out.println(Thread.currentThread().getName()+":-----------------");
			flag = !flag;
			condition.signal();
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}

	public void put() {
		try {
			Thread.sleep(5000);
			lock.lock();
			while (flag) {
				condition.await();
			}
			System.out.println(Thread.currentThread().getName()+":*****************");
			flag = !flag;
			condition.signal();
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}

	public static void main(String[] args) {

		TheadAwait alternatelyPrint = new TheadAwait();
		while (true) {
			new Thread(new Runnable() {
				@Override
				public void run() {
					alternatelyPrint.get();
				}
			}).start();

			new Thread(new Runnable() {
				@Override
				public void run() {
					alternatelyPrint.put();
				}
			}).start();
		}
	}
}

效果:


Callable、Future

Callable: 可理解成執行緒執行的具體任務,但具有返回值 Future:Callable執行的返回值

作用:線上程執行的過程中可獲取到執行緒執行的狀態,例如非同步的情況,可通過執行緒執行後的狀態進行響應的控制,而不至於因為執行緒執行的不確定性造成不可控

注意:future.get() 會造成執行緒阻塞,一致到有返回值才進行下一步操作

  • 測試程式碼
package com.zhiwei.thread;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * callable物件是具有返回值的物件,並且將結果返回給Future物件:
 * completService可以一次執行一組callable獨享方法,並返回最早的結果
 */
public class CallableAndFuture {

	public static void main(String[] args) throws Exception {

		ExecutorService threadPool = Executors.newSingleThreadExecutor();
		Future<String> future = threadPool.submit(new Callable<String>() {
			public String call() throws Exception {
				Thread.sleep(5000);
				return "hello Java World!";
			}
		});
		
		System.out.println("5s執行緒返回結果:" + future.get());
		threadPool.shutdown();
	}
}

效果:5s後

相關推薦

執行- 4執行通訊方式

浪費了“黃金五年”的Java程式設計師,還有救嗎? >>>   

R語言4R包安裝方式

4種R包安裝方式 第一種方式,當然是R自帶的函式直接安裝包了,這個是最簡單的,而且不需要考慮各種包之間的依賴關係。 對普通的R包,直接install.packages()即可,一般下載不了都是包的名字打錯了,或者是R的版本不夠,如果下載了安裝不了,一般是依賴包沒弄好,或者你的電腦缺少一些庫檔

C++114智慧指標

|auto_ptr(不要使用的指標) 沒有智慧指標的c++時代,對堆記憶體的管理就是簡單的new delete。 但是缺點是容易忘了delete釋放,即使是資深碼農,也可能會在某一個地方忘記delete它,造成記憶體洩漏。 在實際工程中,我們往往更希望把精力放在應用層上,而不是費盡心思在語言的細

4程序間通訊方式詳解

     程序間通訊有4種方式,以下從簡單到複雜的方式出場:1.管道(pipe)     管道是一種具有兩個端點的通訊通道,一個管道實際上就是隻存在在記憶體中的檔案,對這個檔案操作需要兩個已經開啟檔案進行,他們代表管道的兩端,也叫兩個句檳,管道是一種特殊的檔案,不屬於一種檔案系統,而是一種獨立的檔案系統,有自

執行- JUC 4執行同步工具

浪費了“黃金五年”的Java程式設計師,還有救嗎? >>>   

《瘋狂Java講義(第4版)》-----第16章執行(控制執行執行同步)

控制執行緒 join執行緒 等那個執行緒做完後,當前執行緒再做! import java.lang.Thread; public class MyThread extends Thread{ public MyThread(String name){ super(

Java併發程式設計:4執行池和緩衝佇列BlockingQueue

一. 執行緒池簡介 1. 執行緒池的概念:           執行緒池就是首先建立一些執行緒,它們的集合稱為執行緒池。使用執行緒池可以很好地提高效能,執行緒池在系統啟動時即建立大量空閒的執行緒,程式將一個任務傳給執行緒池,執行緒池就會啟動一

建立多執行4方式

1.執行緒是什麼?         執行緒被稱為輕量級程序,是程式執行的最小單位,它是指在程式執行過程中,能夠執行程式碼的一個執行單位。每個程式程式都至少有一個執行緒,也即是程式本身。 2.執行緒狀態         Jav

執行4建立方法和對比

Java多執行緒實現方式 Java 多執行緒實現方式主要有四種,繼承Thread,實現Runnable,實現Callable,Future實現返回結果的多執行緒。 1. 繼承Thread類建立 public class MyThread extends Thre

面試題 模擬多執行售票系統

public class Tiket{ private int tiketNumber; public int getTiketNumber() { return tiketNumber; } public void setTiketNumber(int tiketNumber) {

面試總結java多執行

    4.1 ThreadLocal為什麼會產生記憶體洩露(建議結合原始碼學習)       https://blog.csdn.net/puppylpg/article/details/8043

Java程式設計Java多執行的實現

多執行緒 程式:是一個指令的集合。 程序:正在執行中的程式,是一個靜態的概念。 執行緒:是程序中的一個單一的連續控制流程,執行緒又本稱為輕量級程序。 一個程序可擁有多個並行的執行緒,一個程序中的執行緒共享相同的記憶體單元,記憶體地址空間,可以訪問相同的變數和物件,而且他們從

JavaScript高階11、執行機制和事件機制

一、程序與執行緒 1. 程序:程式的一次執行, 它佔有一片獨有的記憶體空間 2. 執行緒: CPU的基本排程單位, 是程式執行的一個完整流程 3. 程序與執行緒 * 一個程序中一般至少有一個執行的執行緒: 主執行緒 * 一個程序中也可以同時執行多個執行緒, 我們會說程式是多執行

JavaScript高階16、執行機制與事件機制筆記

執行緒與程序 程序: 程式的一次執行, 它佔有一片獨有的記憶體空間 可以通過windows工作管理員檢視程序 執行緒: 是程序內的一個獨立執行單元 是程式執行的一個完整流程 是CPU的最小的排

Java建立執行4方式及優缺點

目錄 1. 通過繼承Thread類實現 2. 通過實現Runnable介面實現 3. 通過lambda的方式實現 4. 通過Callable和Future建立執行緒  5. 通過繼承Thread類實現 程式碼展示  6. 通過實現Runnable介面實

Linux學習pthread_create主執行與建立的新執行之間退出關係

我們在一個執行緒中經常會建立另外的新執行緒,如果主執行緒退出,會不會影響它所建立的新執行緒呢?下面就來討論一下。 1、  主執行緒等待新執行緒先結束退出,主執行緒後退出。正常執行。 例項程式碼: #include "apue.h" #include <pthread

java併發多個執行間共享資料

先看一個多執行緒間共享資料的問題: 設計四個執行緒,其中兩個執行緒每次對data增加1,另外兩個執行緒每次對data減少1。   從問題來看,很明顯涉及到了執行緒間通資料的共享,四個執行

Java多執行synchronized與執行安全

介紹 修飾方法:一個執行緒去呼叫一個加synchronized的方法的時候,會獲得該物件的 物件鎖。 修飾靜態方法:一個執行緒去呼叫一個既加static,又加synchronized的方法的時候,會獲得該物件的 類鎖。 修飾程式碼塊: ①加物件鎖:

Executors建立的4執行池的使用

Java通過Executors提供四種執行緒池,分別為: newCachedThreadPool建立一個可快取執行緒池,如果執行緒池長度超過處理需要,可靈活回收空閒執行緒,若無可回收,則新建執行緒。 newFixedThreadPool 建立一個定長執行緒池,可控制執行緒最大

執行之實現執行4方式

什麼是執行緒,簡單的舉個例子 就拿我們的酒店服務員來說,如果只有一個服務員為客人服務的那麼可以把它理解為一個單執行緒工作,但隨著你客人的增加而導致一個服務員忙不過來,而這時你就要請多個服務員了為客人服務了,這個就可以理解成多執行緒工作,說到這裡我想大家都明白了執行緒的作用