[英]static Value Sharing between two Threads Java
我有兩個不同的子進程在兩個不同的線程中運行兩個不同的命令。第二個線程更新靜態變量中的值,第一個線程獲取並使用該值。
流程應該是這樣的:Thread2更新靜態變量,並且thread1從靜態變量中獲取值,然后將其打印..但是發生的流程是thread1首先從靜態變量中獲取了值。 在這種情況下,它具有空值,然后thread2更新該值。
兩個線程並行運行,我正在使用ExecutorService類來執行此操作。 我正在使用Runtime類運行命令,並使用while循環在兩個線程上連續讀取Stream的輸出。
Thread1繼續提供(X,Y)值,線程2僅在獲取文本時才給出值。
(12,123)null-> thread2沒有獲得任何值,因此它不會更新,thread1將從靜態變量獲得null
(123,334)null->線程1從靜態變量中獲取值並使用它,線程2然后將值“ Hello”更新為靜態變量
(134,654)“ Hello”-> thread1拾取並使用“ Hello”,然后thread2將值“ World”更新為靜態變量
(12,123)null-> thread2沒有獲得任何值,因此它不會更新,thread1將從靜態變量獲得null
(123,334)“ Hello”-> thread2將值“ Hello”更新為靜態變量,thread1拾取並使用它
(134,654)“世界”->線程2將值“世界”更新為靜態變量,線程1拾取並使用它
我也使用了volatile變量,但是輸出沒有改變。 我在這里想念什么嗎? 請幫忙...
您可以使用java.util.concurrent.Semaphore(從Java 5開始)來控制同時訪問它們共有的變量的線程數。您可以使用允許執行以下操作的線程數來實例化此類。使用它們的共同點,如果您傳遞0,則意味着他們都不能修改它。
public class Threaad extends Thread{
volatile static String string;
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(0);
Thread writer = new Write(semaphore);
writer.setName("writer");
Thread reader = new Read(semaphore);
reader.setName("reader");
ExecutorService service = Executors.newCachedThreadPool();
service.execute(writer);
service.execute(reader);
service.shutdown();
}
}
class Write extends Thread{
private Semaphore semaphore;
Write(Semaphore semaphore){
this.semaphore = semaphore;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
Threaad.string = String.valueOf(i);
semaphore.release();
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Read extends Thread{
private Semaphore semaphore;
Read(Semaphore semaphore){
this.semaphore = semaphore;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
try {
semaphore.acquire();
System.out.println(Threaad.string);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
使用線程時不要做的事情:在沒有正確同步的情況下寫入和讀取相同的變量。 您違反了此規則,因此遇到了不確定結果的預期問題。
想象以下執行流程:
T1: set var to "Hello"
T2: checks var and notices it is a String, proceeds to print it.
T1: set var to null
T2: prints var. (which is already null again)
可能的解決方案是T2首先將值復制到線程局部變量,然后繼續對該變量進行操作,即:
while (running) {
final String localString = staticString;
if (localString != null) {
System.out.println(localString);
}
}
這樣,您就可以創建變量當前值的“快照”,並且實際上將輸出當時已快照的內容。 但是,這仍然不是在線程之間進行同步的有效方法,因為快照狀態是完全隨機的。 想象發生以下情況:
T1: set var to "hello"
T1: set var to null
T2: checks var, it is null, do nothing.
T1: set var to "world"
T1: set var to null
T2: checks var, it is null, do nothing.
使用線程時,請記住,除非強制執行,否則任何時候任何線程的狀態始終是不確定的。
有幾種簡單的方法可以強制實現特定狀態的synchronized
,這基本上意味着“將整個事情擱置,以便我可以做我的工作”,但是這效率很低,因為如果不斷地將所有內容放在上面,則沒有並行工作的意義。保持。
從架構的角度來看,使用觸發器是一種更好的處理線程的方法。 在您的情況下,編寫器線程可能具有僅包含相關信息(要輸出的字符串)的隊列 ,而生產者線程會將字符串放入該隊列:
T2: checks queue, it is empty, do nothing.
T1: t1.put("Hello")
T2: checks queue, it contains "Hello", print that.
T2: checks queue, it is empty, do nothing.
T2: checks queue, it is empty, do nothing.
T1: t1.put("World")
T2: checks queue, it contains "World", print that.
我建議通讀並發包以了解Java提供的工具。 使用這些幾乎可以解決所有問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.