當前位置:首頁 » 編程語言 » java任務隊列

java任務隊列

發布時間: 2022-06-11 03:22:33

『壹』 java任務隊列用緩存還是資料庫表實現較好

不能簡單說誰好誰壞,各有適用場景。
資料庫在持久化方面比較好,服務宕機,數據還在,但並發性能方面不如緩存。
如果用緩存,最主要是要處理好多線程時線程安全、宕機緩存丟失的問題。如果是分布式部署,同步緩存也要考慮。

『貳』 Java中關於如何實現多線程消息隊列的實例

java中的消息隊列
消息隊列是線程間通訊的手段:

import java.util.*

public class MsgQueue{

private Vector queue = null;
public MsgQueue(){
queue = new Vector();
}
public synchronized void send(Object o)
{
queue.addElement(o);
}
public synchronized Object recv()
{
if(queue.size()==0)
return null;
Object o = queue.firstElement();
queue.removeElementAt(0);//or queue[0] = null can also work
return o;
}
}

因為java中是locked by object的所以添加synchronized 就可以用於線程同步鎖定對象
可以作為多線程處理多任務的存放task的隊列。他的client包括封裝好的task類以及thread類

Java的多線程-線程間的通信2009-08-25 21:58
1. 線程的幾種狀態
線程有四種狀態,任何一個線程肯定處於這四種狀態中的一種:
1) 產生(New):線程對象已經產生,但尚未被啟動,所以無法執行。如通過new產生了一個線程對象後沒對它調用start()函數之前。
2) 可執行(Runnable):每個支持多線程的系統都有一個排程器,排程器會從線程池中選擇一個線程並啟動它。當一個線程處於可執行狀態時,表示它可能正處於線程池中等待排排程器啟動它;也可能它已正在執行。如執行了一個線程對象的start()方法後,線程就處於可執行狀態,但顯而易見的是此時線程不一定正在執行中。
3) 死亡(Dead):當一個線程正常結束,它便處於死亡狀態。如一個線程的run()函數執行完畢後線程就進入死亡狀態。
4) 停滯(Blocked):當一個線程處於停滯狀態時,系統排程器就會忽略它,不對它進行排程。當處於停滯狀態的線程重新回到可執行狀態時,它有可能重新執行。如通過對一個線程調用wait()函數後,線程就進入停滯狀態,只有當兩次對該線程調用notify或notifyAll後它才能兩次回到可執行狀態。
2. classThread下的常用函數函數
2.1 suspend()、resume()
1) 通過suspend()函數,可使線程進入停滯狀態。通過suspend()使線程進入停滯狀態後,除非收到resume()消息,否則該線程不會變回可執行狀態。
2) 當調用suspend()函數後,線程不會釋放它的「鎖標志」。
例11:
class TestThreadMethod extends Thread{
public static int shareVar = 0;
public TestThreadMethod(String name){
super(name);
}
public synchronized void run(){
if(shareVar==0){
for(int i=0; i<5; i++){
shareVar++;
if(shareVar==5){
this.suspend();//(1)
}}}
else{
System.out.print(Thread.currentThread().getName());
System.out.println(" shareVar = " + shareVar);
this.resume();//(2)
}}
}
public class TestThread{
public static void main(String[] args){
TestThreadMethod t1 = new TestThreadMethod("t1");
TestThreadMethod t2 = new TestThreadMethod("t2");
t1.start();//(5)
//t1.start();//(3)
t2.start();//(4)
}}

『叄』 在JAVA中怎麼實現消息隊列

java中的消息隊列
消息隊列是線程間通訊的手段:

importjava.util.*

publicclassMsgQueue{

privateVectorqueue=null;
publicMsgQueue(){
queue=newVector();
}
publicsynchronizedvoidsend(Objecto)
{
queue.addElement(o);
}
publicsynchronizedObjectrecv()
{
if(queue.size()==0)
returnnull;
Objecto=queue.firstElement();
queue.removeElementAt(0);//orqueue[0]=nullcanalsowork
returno;
}
}

因為java中是lockedbyobject的所以添加synchronized就可以用於線程同步鎖定對象
可以作為多線程處理多任務的存放task的隊列。他的client包括封裝好的task類以及thread類

Java的多線程-線程間的通信2009-08-2521:58
1.線程的幾種狀態
線程有四種狀態,任何一個線程肯定處於這四種狀態中的一種:
1)產生(New):線程對象已經產生,但尚未被啟動,所以無法執行。如通過new產生了一個線程對象後沒對它調用start()函數之前。
2)可執行(Runnable):每個支持多線程的系統都有一個排程器,排程器會從線程池中選擇一個線程並啟動它。當一個線程處於可執行狀態時,表示它可能正處於線程池中等待排排程器啟動它;也可能它已正在執行。如執行了一個線程對象的start()方法後,線程就處於可執行狀態,但顯而易見的是此時線程不一定正在執行中。
3)死亡(Dead):當一個線程正常結束,它便處於死亡狀態。如一個線程的run()函數執行完畢後線程就進入死亡狀態。
4)停滯(Blocked):當一個線程處於停滯狀態時,系統排程器就會忽略它,不對它進行排程。當處於停滯狀態的線程重新回到可執行狀態時,它有可能重新執行。如通過對一個線程調用wait()函數後,線程就進入停滯狀態,只有當兩次對該線程調用notify或notifyAll後它才能兩次回到可執行狀態。
2.classThread下的常用函數函數
2.1suspend()、resume()
1)通過suspend()函數,可使線程進入停滯狀態。通過suspend()使線程進入停滯狀態後,除非收到resume()消息,否則該線程不會變回可執行狀態。
2)當調用suspend()函數後,線程不會釋放它的「鎖標志」。
例11:
{
publicstaticintshareVar=0;
publicTestThreadMethod(Stringname){
super(name);
}
publicsynchronizedvoidrun(){
if(shareVar==0){
for(inti=0;i<5;i++){
shareVar++;
if(shareVar==5){
this.suspend();//(1)
}}}
else{
System.out.print(Thread.currentThread().getName());
System.out.println("shareVar="+shareVar);
this.resume();//(2)
}}
}
publicclassTestThread{
publicstaticvoidmain(String[]args){
TestThreadMethodt1=newTestThreadMethod("t1");
TestThreadMethodt2=newTestThreadMethod("t2");
t1.start();//(5)
//t1.start();//(3)
t2.start();//(4)
}}
運行結果為:
t2shareVar=5
i.當代碼(5)的t1所產生的線程運行到代碼(1)處時,該線程進入停滯狀態。然後排程器從線程池中喚起代碼(4)的t2所產生的線程,此時shareVar值不為0,所以執行else中的語句。
ii.也許你會問,那執行代碼(2)後為什麼不會使t1進入可執行狀態呢?正如前面所說,t1和t2是兩個不同對象的線程,而代碼(1)和(2)都只對當前對象進行操作,所以t1所產生的線程執行代碼(1)的結果是對象t1的當前線程進入停滯狀態;而t2所產生的線程執行代碼(2)的結果是把對象t2中的所有處於停滯狀態的線程調回到可執行狀態。
iii.那現在把代碼(4)注釋掉,並去掉代碼(3)的注釋,是不是就能使t1重新回到可執行狀態呢?運行結果是什麼也不輸出。為什麼會這樣呢?也許你會認為,當代碼(5)所產生的線程執行到代碼(1)時,它進入停滯狀態;而代碼(3)所產生的線程和代碼(5)所產生的線程是屬於同一個對象的,那麼就當代碼(3)所產生的線程執行到代碼(2)時,就可使代碼(5)所產生的線程執行回到可執行狀態。但是要清楚,suspend()函數只是讓當前線程進入停滯狀態,但並不釋放當前線程所獲得的「鎖標志」。所以當代碼(5)所產生的線程進入停滯狀態時,代碼(3)所產生的線程仍不能啟動,因為當前對象的「鎖標志」仍被代碼(5)所產生的線程佔有。
#p#2.2sleep()
1)sleep()函數有一個參數,通過參數可使線程在指定的時間內進入停滯狀態,當指定的時間過後,線程則自動進入可執行狀態。
2)當調用sleep()函數後,線程不會釋放它的「鎖標志」。
例12:
{
{
publicstaticintshareVar=0;
publicTestThreadMethod(Stringname){
super(name);
}
publicsynchronizedvoidrun(){
for(inti=0;i<3;i++){
System.out.print(Thread.currentThread().getName());
System.out.println(":"+i);
try{
Thread.sleep(100);//(4)
}
catch(InterruptedExceptione){
System.out.println("Interrupted");
}}}
}
publicclassTestThread{publicstaticvoidmain(String[]args){
TestThreadMethodt1=newTestThreadMethod("t1");
TestThreadMethodt2=newTestThreadMethod("t2");
t1.start();(1)
t1.start();(2)
//t2.start();(3)
}}
運行結果為:
t1:0
t1:1
t1:2
t1:0
t1:1
t1:2
由結果可證明,雖然在run()中執行了sleep(),但是它不會釋放對象的「鎖標志」,所以除非代碼(1)的線程執行完run()函數並釋放對象的「鎖標志」,否則代碼(2)的線程永遠不會執行。
如果把代碼(2)注釋掉,並去掉代碼(3)的注釋,結果將變為:
t1:0
t2:0
t1:1
t2:1
t1:2
t2:2
由於t1和t2是兩個對象的線程,所以當線程t1通過sleep()進入停滯時,排程器會從線程池中調用其它的可執行線程,從而t2線程被啟動。
例13:
{
publicstaticintshareVar=0;
publicTestThreadMethod(Stringname){
super(name);
}
publicsynchronizedvoidrun(){
for(inti=0;i<5;i++){
System.out.print(Thread.currentThread().getName());
System.out.println(":"+i);
try{
if(Thread.currentThread().getName().equals("t1"))
Thread.sleep(200);
else
Thread.sleep(100);
}
catch(InterruptedExceptione){
System.out.println("Interrupted");
}}
}}
publicclassTestThread{publicstaticvoidmain(String[]args){
TestThreadMethodt1=newTestThreadMethod("t1");
TestThreadMethodt2=newTestThreadMethod("t2");
t1.start();
//t1.start();
t2.start();
}}
運行結果為:
t1:0
t2:0
t2:1
t1:1
t2:2
t2:3
t1:2
t2:4
t1:3
t1:4
由於線程t1調用了sleep(200),而線程t2調用了sleep(100),所以線程t2處於停滯狀態的時間是線程t1的一半,從從結果反映出來的就是線程t2列印兩倍次線程t1才列印一次。
#p#2.3yield()
1)通過yield()函數,可使線程進入可執行狀態,排程器從可執行狀態的線程中重新進行排程。所以調用了yield()的函數也有可能馬上被執行。
2)當調用yield()函數後,線程不會釋放它的「鎖標志」。
例14:
{
publicstaticintshareVar=0;
publicTestThreadMethod(Stringname){super(name);
}
publicsynchronizedvoidrun(){for(inti=0;i<4;i++){
System.out.print(Thread.currentThread().getName());
System.out.println(":"+i);
Thread.yield();
}}
}
publicclassTestThread{publicstaticvoidmain(String[]args){
TestThreadMethodt1=newTestThreadMethod("t1");
TestThreadMethodt2=newTestThreadMethod("t2");
t1.start();
t1.start();//(1)
//t2.start();(2)
}
}
運行結果為:
t1:0
t1:1
t1:2
t1:3
t1:0
t1:1
t1:2
t1:3
從結果可知調用yield()時並不會釋放對象的「鎖標志」。
如果把代碼(1)注釋掉,並去掉代碼(2)的注釋,結果為:
t1:0
t1:1
t2:0
t1:2
t2:1
t1:3
t2:2
t2:3
從結果可知,雖然t1線程調用了yield(),但它馬上又被執行了。
2.4sleep()和yield()的區別
1)sleep()使當前線程進入停滯狀態,所以執行sleep()的線程在指定的時間內肯定不會執行;yield()只是使當前線程重新回到可執行狀態,所以執行yield()的線程有可能在進入到可執行狀態後馬上又被執行。
2)sleep()可使優先順序低的線程得到執行的機會,當然也可以讓同優先順序和高優先順序的線程有執行的機會;yield()只能使同優先順序的線程有執行的機會。
例15:
{
publicstaticintshareVar=0;
publicTestThreadMethod(Stringname){
super(name);
}
publicvoidrun(){
for(inti=0;i<4;i++){
System.out.print(Thread.currentThread().getName());
System.out.println(":"+i);
//Thread.yield();(1)
/*(2)*/
try{
Thread.sleep(3000);
}
catch(InterruptedExceptione){
System.out.println("Interrupted");
}}}
}
publicclassTestThread{
publicstaticvoidmain(String[]args){
TestThreadMethodt1=newTestThreadMethod("t1");
TestThreadMethodt2=newTestThreadMethod("t2");
t1.setPriority(Thread.MAX_PRIORITY);
t2.setPriority(Thread.MIN_PRIORITY);
t1.start();
t2.start();
}
}
運行結果為:
t1:0
t1:1
t2:0
t1:2
t2:1
t1:3
t2:2
t2:3
由結果可見,通過sleep()可使優先順序較低的線程有執行的機會。注釋掉代碼(2),並去掉代碼(1)的注釋,結果為:
t1:0
t1:1
t1:2
t1:3
t2:0
t2:1
t2:2
t2:3
可見,調用yield(),不同優先順序的線程永遠不會得到執行機會。
2.5join()
使調用join()的線程執行完畢後才能執行其它線程,在一定意義上,它可以實現同步的功能。
例16:
{
publicstaticintshareVar=0;
publicTestThreadMethod(Stringname){
super(name);
}
publicvoidrun(){
for(inti=0;i<4;i++){
System.out.println(""+i);
try{
Thread.sleep(3000);
}
catch(InterruptedExceptione){
System.out.println("Interrupted");
}
}
}
}
publicclassTestThread{
publicstaticvoidmain(String[]args){
TestThreadMethodt1=newTestThreadMethod("t1");
t1.start();
try{
t1.join();
}
catch(InterruptedExceptione){}
t1.start();
}
}
運行結果為:
0
1
2
3
0
1
2
3
#p#3.classObject下常用的線程函數
wait()、notify()和notifyAll()這三個函數由java.lang.Object類提供,用於協調多個線程對共享數據的存取。
3.1wait()、notify()和notifyAll()
1)wait()函數有兩種形式:第一種形式接受一個毫秒值,用於在指定時間長度內暫停線程,使線程進入停滯狀態。第二種形式為不帶參數,代表waite()在notify()或notifyAll()之前會持續停滯。
2)當對一個對象執行notify()時,會從線程等待池中移走該任意一個線程,並把它放到鎖標志等待池中;當對一個對象執行notifyAll()時,會從線程等待池中移走所有該對象的所有線程,並把它們放到鎖標志等待池中。
3)當調用wait()後,線程會釋放掉它所佔有的「鎖標志」,從而使線程所在對象中的其它synchronized數據可被別的線程使用。
例17:
下面,我們將對例11中的例子進行修改
{
publicstaticintshareVar=0;
publicTestThreadMethod(Stringname){
super(name);
}
publicsynchronizedvoidrun(){
if(shareVar==0){
for(inti=0;i<10;i++){
shareVar++;
if(shareVar==5){
try{
this.wait();//(4)
}
catch(InterruptedExceptione){}
}
}
}
if(shareVar!=0){
System.out.print(Thread.currentThread().getName());
System.out.println("shareVar="+shareVar);
this.notify();//(5)
}
}
}
publicclassTestThread{
publicstaticvoidmain(String[]args){
TestThreadMethodt1=newTestThreadMethod("t1");
TestThreadMethodt2=newTestThreadMethod("t2");
t1.start();//(1)
//t1.start();(2)
t2.start();//(3)
}}
運行結果為:
t2shareVar=5
因為t1和t2是兩個不同對象,所以線程t2調用代碼(5)不能喚起線程t1。如果去掉代碼(2)的注釋,並注釋掉代碼(3),結果為:
t1shareVar=5
t1shareVar=10
這是因為,當代碼(1)的線程執行到代碼(4)時,它進入停滯狀態,並釋放對象的鎖狀態。接著,代碼(2)的線程執行run(),由於此時shareVar值為5,所以執行列印語句並調用代碼(5)使代碼(1)的線程進入可執行狀態,然後代碼(2)的線程結束。當代碼(1)的線程重新執行後,它接著執行for()循環一直到shareVar=10,然後列印shareVar。
#p#3.2wait()、notify()和synchronized
waite()和notify()因為會對對象的「鎖標志」進行操作,所以它們必須在synchronized函數或synchronizedblock中進行調用。如果在non-synchronized函數或non-synchronizedblock中進行調用,雖然能編譯通過,但在運行時會發生IllegalMonitorStateException的異常。
例18:
{
publicintshareVar=0;
publicTestThreadMethod(Stringname){
super(name);
newNotifier(this);
}
publicsynchronizedvoidrun(){
if(shareVar==0){
for(inti=0;i<5;i++){
shareVar++;
System.out.println("i="+shareVar);
try{
System.out.println("wait......");
this.wait();
}
catch(InterruptedExceptione){}
}}
}
}
classNotifierextendsThread{
privateTestThreadMethodttm;
Notifier(TestThreadMethodt){
ttm=t;
start();
}
publicvoidrun(){
while(true){
try{
sleep(2000);
}
catch(InterruptedExceptione){}
/*1要同步的不是當前對象的做法*/
synchronized(ttm){
System.out.println("notify......");
ttm.notify();
}}
}
}
publicclassTestThread{
publicstaticvoidmain(String[]args){
TestThreadMethodt1=newTestThreadMethod("t1");
t1.start();
}
}
運行結果為:
i=1
wait......
notify......
i=2
wait......
notify......
i=3
wait......
notify......
i=4
wait......
notify......
i=5
wait......
notify......
4.wait()、notify()、notifyAll()和suspend()、resume()、sleep()的討論
4.1這兩組函數的區別
1)wait()使當前線程進入停滯狀態時,還會釋放當前線程所佔有的「鎖標志」,從而使線程對象中的synchronized資源可被對象中別的線程使用;而suspend()和sleep()使當前線程進入停滯狀態時不會釋放當前線程所佔有的「鎖標志」。
2)前一組函數必須在synchronized函數或synchronizedblock中調用,否則在運行時會產生錯誤;而後一組函數可以non-synchronized函數和synchronizedblock中調用。
4.2這兩組函數的取捨
Java2已不建議使用後一組函數。因為在調用suspend()時不會釋放當前線程所取得的「鎖標志」,這樣很容易造成「死鎖」。

『肆』 javaweb任務列隊怎麼做

1.在同一時刻,可能有很多任務需要執行,
而程序在同一時刻只能執行一定數量的任務,
當需要執行的任務數超過了程序所能承受的任務數時怎麼辦呢?
這就有了先執行哪些任務,後執行哪些任務的規則。
2.TaskQueue類就定義了這些規則中的一種,它採用的是FIFO(先進先出,英文名是First
In
First
Out)的方式,也就是按照任務到達的先後順序執行。TaskQueue類的定義。

Java任務隊列代碼如下:

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
public class TaskQueue
{
private List<Task>
queue = new LinkedList<Task>();
//
添加一項任務

public synchronized void addTask(Task
task) {
if (task
!= null)
{
queue.add(task);
}
}
//
完成任務後將它從任務隊列中刪除

public synchronized void finishTask(Task
task) {
if (task
!= null)
{
task.setState(Task.State.FINISHED);
queue.remove(task);
}
}
//
取得一項待執行任務

public synchronized Task
getTask() {
Iterator<Task>
it = queue.iterator();
Task
task;
while (it.hasNext())
{
task
= it.next(); //
尋找一個新建的任務
if (Task.State.NEW.equals(task.getState()))
{ //
把任務狀態置為運行中
task.setState(Task.State.RUNNING);
return task;
}
}
return null;
}
}

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
public class TaskQueue
{
private List<Task>
queue = new LinkedList<Task>();
//
添加一項任務
public synchronized void addTask(Task
task) {
if (task
!= null)
{
queue.add(task);
}
}
//
完成任務後將它從任務隊列中刪除

public synchronized void finishTask(Task
task) {
if (task
!= null)
{
task.setState(Task.State.FINISHED);
queue.remove(task);
}
}
//
取得一項待執行任務

public synchronized Task
getTask() {
Iterator<Task>
it = queue.iterator();
Task
task;
while (it.hasNext())
{
task
= it.next(); //
尋找一個新建的任務
if (Task.State.NEW.equals(task.getState()))
{ //
把任務狀態置為運行中
task.setState(Task.State.RUNNING);
return task;
}
}
return null;
}
}

『伍』 到底什麼是消息隊列Java中如何實現消息隊列

「消息隊列」是在消息的傳輸過程中保存消息的容器。和我們學過的LinkedHashMap,TreeSet等一樣,都是容器。既然是容器,就有有自己的特性,就像LinkedHashMap是以鍵值對存儲。存取順序不變。而消息隊列,看到隊列就可以知道。這個容器裡面的消息是站好隊的,一般遵從先進先出原則。

java中已經為我們封裝好了很多的消息隊列。在java 1.5版本時推出的java.util.concurrent中有很多現成的隊列供我們使用。特性繁多,種類齊全。是你居家旅遊開發必備QAQ。

下面簡單列舉這個包中的消息隊列

  1. :阻塞隊列 BlockingQueue

  2. 數組阻塞隊列 ArrayBlockingQueue

  3. 延遲隊列 DelayQueue

  4. 鏈阻塞隊列 LinkedBlockingQueue

  5. 具有優先順序的阻塞隊列 PriorityBlockingQueue

  6. 同步隊列 SynchronousQueue

  7. 阻塞雙端隊列 BlockingDeque

  8. 鏈阻塞雙端隊列 LinkedBlockingDeque

    不同的隊列不同的特性決定了隊列使用的時機,感興趣的話你可以詳細了解。具體的使用方式我就不贅述了

『陸』 java 線程池 工作隊列是如何工作的

使用線程池的好處

1、降低資源消耗

可以重復利用已創建的線程降低線程創建和銷毀造成的消耗。

2、提高響應速度

當任務到達時,任務可以不需要等到線程創建就能立即執行。

3、提高線程的可管理性

線程是稀缺資源,如果無限制地創建,不僅會消耗系統資源,還會降低系統的穩定性,使用線程池可以進行統一分配、調優和監控

線程池的工作原理

首先我們看下當一個新的任務提交到線程池之後,線程池是如何處理的

1、線程池判斷核心線程池裡的線程是否都在執行任務。如果不是,則創建一個新的工作線程來執行任務。如果核心線程池裡的線程都在執行任務,則執行第二步。

2、線程池判斷工作隊列是否已經滿。如果工作隊列沒有滿,則將新提交的任務存儲在這個工作隊列里進行等待。如果工作隊列滿了,則執行第三步

3、線程池判斷線程池的線程是否都處於工作狀態。如果沒有,則創建一個新的工作線程來執行任務。如果已經滿了,則交給飽和策略來處理這個任務

線程池飽和策略

這里提到了線程池的飽和策略,那我們就簡單介紹下有哪些飽和策略:

AbortPolicy

為Java線程池默認的阻塞策略,不執行此任務,而且直接拋出一個運行時異常,切記ThreadPoolExecutor.execute需要try catch,否則程序會直接退出。

DiscardPolicy

直接拋棄,任務不執行,空方法

DiscardOldestPolicy

從隊列裡面拋棄head的一個任務,並再次execute 此task。

CallerRunsPolicy

在調用execute的線程裡面執行此command,會阻塞入口

用戶自定義拒絕策略(最常用)

實現RejectedExecutionHandler,並自己定義策略模式

下我們以ThreadPoolExecutor為例展示下線程池的工作流程圖

3.jpg

關鍵方法源碼分析

我們看看核心方法添加到線程池方法execute的源碼如下:

// //Executes the given task sometime in the future. The task //may execute in a new thread or in an existing pooled thread. // // If the task cannot be submitted for execution, either because this // executor has been shutdown or because its capacity has been reached, // the task is handled by the current {@code RejectedExecutionHandler}. // // @param command the task to execute // @throws RejectedExecutionException at discretion of // {@code RejectedExecutionHandler}, if the task // cannot be accepted for execution // @throws NullPointerException if {@code command} is null // public void execute(Runnable command) { if (command == null) throw new NullPointerException(); // // Proceed in 3 steps: // // 1. If fewer than corePoolSize threads are running, try to // start a new thread with the given command as its first // task. The call to addWorker atomically checks runState and // workerCount, and so prevents false alarms that would add // threads when it shouldn't, by returning false. // 翻譯如下: // 判斷當前的線程數是否小於corePoolSize如果是,使用入參任務通過addWord方法創建一個新的線程, // 如果能完成新線程創建exexute方法結束,成功提交任務 // 2. If a task can be successfully queued, then we still need // to double-check whether we should have added a thread // (because existing ones died since last checking) or that // the pool shut down since entry into this method. So we // recheck state and if necessary roll back the enqueuing if // stopped, or start a new thread if there are none. // 翻譯如下: // 在第一步沒有完成任務提交;狀態為運行並且能否成功加入任務到工作隊列後,再進行一次check,如果狀態 // 在任務加入隊列後變為了非運行(有可能是在執行到這里線程池shutdown了),非運行狀態下當然是需要 // reject;然後再判斷當前線程數是否為0(有可能這個時候線程數變為了0),如是,新增一個線程; // 3. If we cannot queue task, then we try to add a new // thread. If it fails, we know we are shut down or saturated // and so reject the task. // 翻譯如下: // 如果不能加入任務到工作隊列,將嘗試使用任務新增一個線程,如果失敗,則是線程池已經shutdown或者線程池 // 已經達到飽和狀態,所以reject這個他任務 // int c = ctl.get(); // 工作線程數小於核心線程數 if (workerCountOf(c) < corePoolSize) { // 直接啟動新線程,true表示會再次檢查workerCount是否小於corePoolSize if (addWorker(command, true)) return; c = ctl.get(); } // 如果工作線程數大於等於核心線程數 // 線程的的狀態未RUNNING並且隊列notfull if (isRunning(c) && workQueue.offer(command)) { // 再次檢查線程的運行狀態,如果不是RUNNING直接從隊列中移除 int recheck = ctl.get(); if (! isRunning(recheck) && remove(command)) // 移除成功,拒絕該非運行的任務 reject(command); else if (workerCountOf(recheck) == 0) // 防止了SHUTDOWN狀態下沒有活動線程了,但是隊列里還有任務沒執行這種特殊情況。 // 添加一個null任務是因為SHUTDOWN狀態下,線程池不再接受新任務 addWorker(null, false); } // 如果隊列滿了或者是非運行的任務都拒絕執行 else if (!addWorker(command, false)) reject(command); }

『柒』 JAVA中,常用的隊列實現是哪個

隊列的實現單純的是數據結構的問題,既可以用鏈表結構實現隊列,也可以用數組實現。這和語言不是緊密關系,java可以這樣實現,c、c++
也可以。

『捌』 java中如何實現按隊列執行任務

package com.tone.example;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.tone.task.TaskProperty;
import com.tone.task.TaskSignature;
import com.tone.task.impl.BasicTask;
import com.tone.task.runner.TaskRunner;

/**
* 任務隊列示常式序
* @author zlf
*/
public class TaskExample {
private TaskRunner taskRunner;

/**
* 做任務隊列的初始化工作
*/
@Before
public void init() {
// 獲取任務運行器
taskRunner = TaskRunner.getInstance();
// 將任務運行器放入線程進行調度
Thread thread = new Thread(taskRunner);
thread.start();
}

/**
* 等待任務執行完成,並做最後的退出工作
*/
@After
public void exit() throws InterruptedException {
Thread.sleep(600);
System.exit(0);
}

/**
* 最簡單的任務運行示例
*/
@Test
public void example1() {
// 添加任務到任務運行器
taskRunner.addTask(new BasicTask() {
@Override
public void run() {
System.out.println("This is running in task runner thread, and thread is " + Thread.currentThread());
}
});
}

/**
* 加入優先執行順序的任務運行器
*/
@Test
public void example2() {
// 添加任務到任務運行器
taskRunner.addTask(new BasicTask(0) {
@Override
public void run() {
System.out.println("This is a normal task");
}
});
taskRunner.addTask(new BasicTask(-1) {
@Override
public void run() {
System.out.println("This is a task a bit high than normal");
}
});
}

/**
* 重復添加的任務只會運行第一個
*/
@Test
public void example3() {
// 添加任務到任務運行器
taskRunner.addTask(new BasicTask(TaskSignature.ONE) {
@Override
public void run() {
System.out.println("This is task one");
}
}, TaskProperty.NOT_REPEAT);
taskRunner.addTask(new BasicTask(TaskSignature.ONE) {
@Override
public void run() {
System.out.println("This is also task one");
}
}, TaskProperty.NOT_REPEAT);
}

/**
* 重復添加的任務只會運行最後一個
*/
@Test
public void example4() {
// 添加任務到任務運行器
taskRunner.addTask(new BasicTask(TaskSignature.ONE) {
@Override
public void run() {
System.out.println("This is task one");
}
}, TaskProperty.NOT_REPEAT_OVERRIDE);
taskRunner.addTask(new BasicTask(TaskSignature.ONE) {
@Override
public void run() {
System.out.println("This is also task one");
}
}, TaskProperty.NOT_REPEAT_OVERRIDE);
}
}

『玖』 java 隊列

我說一種情況吧。隊列可以用於數據緩沖,比如你一個線程接收數據,這個數據可能會一段時間來的非常迅猛,一段時間又來的比較溫和,這個時候你就可以做一個隊列,一個線程把接收的數據存放到隊列,另外的線程慢慢處理數據,在數據來的迅猛的時候,因為有隊列的緩沖,你處理數據的線程就算處理不過,也不會直接導致系統崩潰,等數據來的溫和的時候,就可以慢慢的消化之前在隊列來不及處理的數據。

『拾』 java隊列實現非同步執行

在整個思路上要調整一下

1、會有很多線程給一個隊列上添加任務

2、有一個或者多個線程逐個執行隊列的任務


考慮一下幾點:

1、沒有任務時,隊列執行線程處於等待狀態

2、添加任務時,激活隊列執行線程,全部run起來,首先搶到任務的執行,其他全部wait


給個小例子吧

packageorg;
importjava.util.LinkedList;
importjava.util.List;
publicclassQueues{
publicstaticList<Task>queue=newLinkedList<Task>();
/**
*假如參數o為任務
*@paramo
*/
publicstaticvoidadd(Taskt){
synchronized(Queues.queue){
Queues.queue.add(t);//添加任務
Queues.queue.notifyAll();//激活該隊列對應的執行線程,全部Run起來
}
}
staticclassTask{
publicvoidtest(){
System.out.println("我被執行了");
}
}
}
packageorg;
importjava.util.List;
{
@Override
publicvoidrun(){
while(true){
synchronized(Queues.queue){
while(Queues.queue.isEmpty()){//
try{
Queues.queue.wait();//隊列為空時,使線程處於等待狀態
}catch(InterruptedExceptione){
e.printStackTrace();
}
System.out.println("wait...");
}
Queues.Taskt=Queues.queue.remove(0);//得到第一個
t.test();//執行該任務
System.out.println("end");
}
}
}
publicstaticvoidmain(String[]args){
Exece=newExec();
for(inti=0;i<2;i++){
newThread(e).start();//開始執行時,隊列為空,處於等待狀態
}
//上面開啟兩個線程執行隊列中的任務,那就是先到先得了
//添加一個任務測試
Queues.Taskt=newQueues.Task();
Queues.add(t);//執行該方法,激活所有對應隊列,那兩個線程就會開始執行啦
}

}


上面的就是很簡單的例子了

熱點內容
java中set集合 發布:2025-02-07 22:43:34 瀏覽:30
播放這個wifi密碼是多少 發布:2025-02-07 22:34:54 瀏覽:99
視頻存儲時間長了有雪花 發布:2025-02-07 22:24:34 瀏覽:568
哈佛f7x怎麼區分配置 發布:2025-02-07 22:22:34 瀏覽:771
廣州python培訓 發布:2025-02-07 22:22:26 瀏覽:199
陸金所的交易密碼是什麼 發布:2025-02-07 22:19:25 瀏覽:320
如何刪除平板儲存密碼 發布:2025-02-07 22:10:29 瀏覽:747
php微信授權登錄 發布:2025-02-07 22:10:27 瀏覽:378
怎樣編程時鍾 發布:2025-02-07 21:59:38 瀏覽:562
誇克編程 發布:2025-02-07 21:43:43 瀏覽:530