話不多說,先上代碼:
public class BIOTest {
public static void main(String[] args) throws IOException {
ExecutorService eService= new ThreadPoolExecutor(
1,
Runtime.getRuntime().availableProcessors(),
5,
TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()
);
ServerSocket sSocket=new ServerSocket(9527);
System.out.println("服務開始");
while(true) {
//監聽
final Socket socket=sSocket.accept();
System.out.println("有人進來了");
eService.execute(()->{
handler(socket);
});
}
}
public static void handler(Socket socket) {
try {
// System.out.println("當前執行緒為:"+Thread.currentThread().getName());
byte[] bytes=new byte[1024];
InputStream inp =socket.getInputStream();
while(true) {
int read = inp.read(bytes);
if(read!=-1) {
System.out.println(Thread.currentThread().getName()+":"+new String(bytes,0,read));
}else {break;}
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}finally {
System.out.println(Thread.currentThread().getName()+" OUT");
try {
socket.close();
} catch (Exception e2) {
// TODO: handle exception
e2.printStackTrace();
}
}
}
}
現在得問題是,當我使用Linked/ArrayBlockingQueue的時候,使用命令telnet 127.0.0.1 9527一直都只有一條執行緒,兩個視窗運行這個命令會形成阻塞,必須關閉第一個視窗使得第二個視窗發送得資訊得以發送給服務端,但使用SynchronousQueue就沒有這個問題,為什么呢?
uj5u.com熱心網友回復:
我去,怎么修改了我原本得意思,不是中斷吧,是第二個視窗發送得訊息無法在控制臺輸出,必須關閉第一個視窗,第二個視窗發送得資訊才得以輸出,最主要是不知道為什么執行緒只有一條但使用SynchronousQueue就沒有這個問題uj5u.com熱心網友回復:
釋放資源問題吧。SynchronousQueue這個應該會自動釋放資源,其他需要手動釋放吧uj5u.com熱心網友回復:
世上沒有奇怪的問題,只有沒有研究透的問題。把執行緒池核心執行緒數改大試試。
uj5u.com熱心網友回復:
執行緒池執行順序 核心執行緒->等待佇列->最大執行緒 ,你核心執行緒數就1,而且用的是LinkedBlockingQueue,當然只有一個執行緒能正常操作,另外一個執行緒任務都被存在佇列中了,并不會開啟新執行緒去執行,而SynchronousQueue這個佇列其實是特殊的阻塞佇列,它內部實際不會存盤任務,你可以去看看SynchronousQueue的特點uj5u.com熱心網友回復:
這個我知道,我專門看了帖子才來發問的,帖子是這個:https://blog.csdn.net/qq_26881739/article/details/80983495
我只是很疑惑,稍微配合一下靠近業務的代碼就這個效果,之前看的時候就是for回圈執行執行緒池是沒有這個問題的
uj5u.com熱心網友回復:
我記得有個類似.close()的方法可以呼叫,使用這個釋放嗎?
uj5u.com熱心網友回復:
你的執行緒池容量只有1,用SynchronousQueue,兩個視窗除非是完全同一時間片在發訊息,否則肯定是一個執行緒先消費完SynchronousQueue佇列然后退出了,然后第二個視窗再用池里面的執行緒再消費SynchronousQueue佇列,當然不會阻塞,我不相信你如果是同一時間戳在發訊息,用SynchronousQueue還可以并行你可以寫一個客戶端來模擬,sleep下讓執行緒不要馬上退出,再試試SynchronousQueue
另外你想實作什么業務場景呢? 如果想精確的執行緒邏輯并且控制并發粒度,建議你用concurrent包下的各種鎖,而不要依靠ExecutorThread里面的佇列容器
uj5u.com熱心網友回復:
那你疑惑什么,你的問題是什么,你發的帖子看了下,就是簡單的介紹了下三種佇列,你可以試著把你的表述弄的簡潔一點uj5u.com熱心網友回復:
那你疑惑什么,你的問題是什么,你發的帖子看了下,就是簡單的介紹了下三種佇列,你可以試著把你的表述弄的簡潔一點
執行緒池執行順序 核心執行緒->等待佇列->最大執行緒 ,你核心執行緒數就1,而且用的是LinkedBlockingQueue,當然只有一個執行緒能正常操作,另外一個執行緒任務都被存在佇列中了,并不會開啟新執行緒去執行,而SynchronousQueue這個佇列其實是特殊的阻塞佇列,它內部實際不會存盤任務,你可以去看看SynchronousQueue的特點
這個我知道,我專門看了帖子才來發問的,帖子是這個:https://blog.csdn.net/qq_26881739/article/details/80983495
我只是很疑惑,稍微配合一下靠近業務的代碼就這個效果,之前看的時候就是for回圈執行執行緒池是沒有這個問題的
我的我的,想都沒想就提問了,我只想知道為什么只有一條核心執行緒作業,明明指認了最大核心執行緒
uj5u.com熱心網友回復:
你的執行緒池容量只有1,用SynchronousQueue,兩個視窗除非是完全同一時間片在發訊息,否則肯定是一個執行緒先消費完SynchronousQueue佇列然后退出了,然后第二個視窗再用池里面的執行緒再消費SynchronousQueue佇列,當然不會阻塞,我不相信你如果是同一時間戳在發訊息,用SynchronousQueue還可以并行
你可以寫一個客戶端來模擬,sleep下讓執行緒不要馬上退出,再試試SynchronousQueue
另外你想實作什么業務場景呢? 如果想精確的執行緒邏輯并且控制并發粒度,建議你用concurrent包下的各種鎖,而不要依靠ExecutorThread里面的佇列容器
意思是其他佇列不會主動釋放資源所以會阻塞是吧?其實也沒有相關的業務場景,就是想練一練,java并發包還是模模糊糊的,待會試一下
uj5u.com熱心網友回復:
針對你一樓說的問題,我是這么認為的當執行的任務超過核心執行緒數corePoolSize,超出的任務會放到佇列里,當超出的任務超過佇列長度時,最大執行緒數maximumPoolSize這個引數開始起作用,超出的任務執行緒池會啟動新的執行緒去執行這些任務(這些新創建的執行緒數量不超過maximumPoolSize-corePoolSize)
你代碼使用LinkedBlockingQueue,核心執行緒數為1,佇列長度為3
當你添加第二個任務的時候(也就是連接第二個視窗的時候),第二個任務被放進佇列等待消費(知道第一個任務被消費)
重點來了,你使用了SynchronousQueue這個佇列,這個佇列是沒有長度的,
也就是說添加第二個任務的時候,maximumPoolSize開始生效(也就是執行緒池會新增執行緒去執行第二個任務)
備注
(1)使用LinkedBlockingQueue,你把長度設定為1,然后開3個視窗去連接
(2)使用SynchronousQueue,maximumPoolSize設定為1,然后開2個視窗去連接
按備注操作一下分析一下估計就明白我說啥了
uj5u.com熱心網友回復:
針對你一樓說的問題,我是這么認為的
當執行的任務超過核心執行緒數corePoolSize,超出的任務會放到佇列里,當超出的任務超過佇列長度時,最大執行緒數maximumPoolSize這個引數開始起作用,超出的任務執行緒池會啟動新的執行緒去執行這些任務(這些新創建的執行緒數量不超過maximumPoolSize-corePoolSize)
你代碼使用LinkedBlockingQueue,核心執行緒數為1,佇列長度為3
當你添加第二個任務的時候(也就是連接第二個視窗的時候),第二個任務被放進佇列等待消費(知道第一個任務被消費)
重點來了,你使用了SynchronousQueue這個佇列,這個佇列是沒有長度的,
也就是說添加第二個任務的時候,maximumPoolSize開始生效(也就是執行緒池會新增執行緒去執行第二個任務)
備注
(1)使用LinkedBlockingQueue,你把長度設定為1,然后開3個視窗去連接
(2)使用SynchronousQueue,maximumPoolSize設定為1,然后開2個視窗去連接
按備注操作一下分析一下估計就明白我說啥了
明白了,感謝大佬,我本該去看原始碼的,麻煩你們了!
uj5u.com熱心網友回復:
那你疑惑什么,你的問題是什么,你發的帖子看了下,就是簡單的介紹了下三種佇列,你可以試著把你的表述弄的簡潔一點
執行緒池執行順序 核心執行緒->等待佇列->最大執行緒 ,你核心執行緒數就1,而且用的是LinkedBlockingQueue,當然只有一個執行緒能正常操作,另外一個執行緒任務都被存在佇列中了,并不會開啟新執行緒去執行,而SynchronousQueue這個佇列其實是特殊的阻塞佇列,它內部實際不會存盤任務,你可以去看看SynchronousQueue的特點
這個我知道,我專門看了帖子才來發問的,帖子是這個:https://blog.csdn.net/qq_26881739/article/details/80983495
我只是很疑惑,稍微配合一下靠近業務的代碼就這個效果,之前看的時候就是for回圈執行執行緒池是沒有這個問題的
我的我的,想都沒想就提問了,我只想知道為什么只有一條核心執行緒作業,明明指認了最大核心執行緒
uj5u.com熱心網友回復:
11111111111111uj5u.com熱心網友回復:
執行緒池執行順序 核心執行緒->等待佇列->最大執行緒 ,你核心執行緒數就1,而且用的是LinkedBlockingQueue,當然只有一個執行緒能正常操作,另外一個執行緒任務都被存在佇列中了,并不會開啟新執行緒去執行,而SynchronousQueue這個佇列其實是特殊的阻塞佇列,它內部實際不會存盤任務,你可以去看看SynchronousQueue的特點
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/59190.html
標籤:Java EE
上一篇:Java運行以后出現問題,求修改
