2017-07-16 79 views
2

所以我寫的程序如下:線程停止,但仍與假布爾值(Java)的運行

import java.util.Random; 
import java.util.Scanner; 
import java.util.concurrent.ArrayBlockingQueue; 
import java.util.concurrent.BlockingQueue; 

public class JustAClass{ 

    private volatile static boolean tof=true; 

    private static void stop(){ 
     tof=false; 
    } 

    private static BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(10); 

    private static void producer() throws InterruptedException{ 
     while(tof){ 
      Random random = new Random(); 
      queue.put(random.nextInt(100)); 
      System.out.println("........"); 
     } 
    } 
    private static void consumer() throws InterruptedException{ 
     while(tof){ 
     Random random = new Random(); 
      Thread.sleep(100); 
      if(random.nextInt(10)==0){ 
       Integer value = queue.take(); 

       System.out.println("Value taken: "+value+"; Queue size: "+queue.size()); 
      } 
     } 
    } 



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

     Scanner scanner = new Scanner(System.in); 
     System.out.println("Press Enter to terminate"); 

     Thread t1 = new Thread(new Runnable(){ 
      public void run(){ 
       try { 
        producer(); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      } 
      }); 

     Thread t2 = new Thread(new Runnable(){ 
      public void run(){ 
       try { 
        consumer(); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      } 
     }); 
     t1.start(); 
     t2.start(); 

     scanner.nextLine(); 
     stop(); 

     t1.join(); 
     t2.join(); 

     System.out.println("Terminated"); 
    } 
} 

控制檯通常表明這一點:

Press Enter to terminate 
........ 
........ 
........ 
........ 
........ 
........ 
........ 
........ 
........ 
........ 
........ 
Value taken: 58; Queue size: 10 
Value taken: 53; Queue size: 9 
........ 
Value taken: 9; Queue size: 9 
........ 

的程序必須中止一次我按Enter鍵。雖然輸出停止,但不會顯示消息「終止」。這意味着線程仍然必須運行。我哪裏做錯了? 另外,在某些情況下,顯示消息「Terminated」並且線程停止。爲什麼?

+0

我看不到的方式關閉掃描儀放置在 – Marvin

+3

你代碼可能被阻塞'queue.take()' – assylias

+1

@Marvin在這裏沒有必要 – assylias

回答

1

添加這裏的線,

System.out.println(t1.getState()+" "+t2.getState()+" "+queue.size()); 
     t1.join(); 
     t2.join(); 

你會得到的想法。製片人正在等待,因爲隊列的大小爲10。它繼續,大小必須小於10。所以,有時候你的病情

if(random.nextInt(10)==0){ 
      Integer value = queue.take(); 

      System.out.println("Value taken: "+value+"; Queue size: "+queue.size()); 
     } 

有可能成爲真正的,它可能會重新運行模式。在其餘時間,它會一直等到永遠,所以你的主線。

1

此行爲是因爲BlockingQueue界面如何工作。在完成所有線程之前,請確保已調用drainTo方法,否則,colour會等待將值返回給不再存在的線程。有關的BlockingQueue如何工作的更多信息,請BlockingQueue Documentation

一個possilbe解決方案是:到consumer方法和while循環之後添加此條件

if (!tof) queue.drainTo(new ArrayList<>()); 

這是conumer方法看起來像以完成程序

private static void consumer() throws InterruptedException{ 
    while(tof){ 
     Random random = new Random(); 
     Thread.sleep(100); 
     if(random.nextInt(10)==0){ 
      Integer value = queue.take(); 

      System.out.println("Value taken: "+value+"; Queue size: "+queue.size()); 
     } 
    } 
    if (!tof) queue.drainTo(new ArrayList<>()); 
} 

希望這會有所幫助。

方案2:程序等到隊列爲空。轉到消費者的方法,去while條件和驗證,如果隊列不爲空!queue.isEmpty()

這是2如何另類的樣子:

private static void consumer() throws InterruptedException{ 

     while(tof || !queue.isEmpty()){ 
      Random random = new Random(); 
      Thread.sleep(100); 
      if(random.nextInt(10)==0){ 
       Integer value = queue.take(); 

       System.out.println("Value taken: "+value+"; Queue size: "+queue.size()); 
      } 
     } 
     // if (!tof) queue.drainTo(new ArrayList<>()); possible solution 1 
    } 
+0

我用你的第一個解決方案,它的工作!謝謝!! – Ken