當前位置:首頁 » 編程語言 » 生產者消費者java

生產者消費者java

發布時間: 2023-04-11 05:22:50

A. java 生產者消費者 線程優先順序問題

1、容器或者線程在生產或消費時需要先判斷容器是否為空、是否已滿,容器沒有自定義的話,就要在線程類中每次生產之前判斷容器是否已滿(這個已經由容器判斷),在消費時要判斷容器是否為空

2、一般,線程同步最好用synchronized關鍵字鎖定同步代碼,然後通過wait()和notify()方法實現線程同步,不過容器容量大一點才能看到效果。代碼如下:
class BQProc implements Runnable {
private BlockingQueue<Integer>拍梁歷 queue;

public BQProc(BlockingQueue<Integer> queue) {
this.queue = queue;
}

public void run() {
synchronized(queue) {
for (int proct = 1; proct <= 10; proct++) {

try {
if(queue.size() == 5) {
queue.wait();
}
queue.put(proct);// 放進去一個
System.out.println("放在 --> " + this.queue.size());
queue.notify();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}

class BQConsume implements Runnable {
private BlockingQueue<Integer> queue;

public BQConsume(BlockingQueue<Integer> queue) {
this.queue = queue;
}

public void run() {
synchronized(queue) {
for (int i = 1; i <= 10; i++) {
try {
if(queue.isEmpty()) {
queue.wait();
}
System.out.println("拿出 <-- " + this.queue.size());
queue.take();// 拿出來一個
queue.notify();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
運行結果:
放在 --> 1
放在 --> 2
放在 --> 3
放在 -->襲搜 4
放在 --> 5
拿出 <-- 5
拿出 <-- 4
拿出 <-- 3
拿出渣凳 <-- 2
拿出 <-- 1
放在 --> 1
放在 --> 2
放在 --> 3
放在 --> 4
放在 --> 5
拿出 <-- 5
拿出 <-- 4
拿出 <-- 3
拿出 <-- 2
拿出 <-- 1

PS:當基數大到一定程度才可以看到想要的結果
3、如果一定要用Thread.sleep()實現的話可以用循環控制,代碼如下:

class BQProc implements Runnable {
private BlockingQueue<Integer> queue;

public BQProc(BlockingQueue<Integer> queue) {
this.queue = queue;
}

public void run() {
for (int proct = 1; proct <= 10; proct++) {

try {
while(queue.size() == 5) {
Thread.sleep(1000);
}
Thread.sleep((int) (Math.random() * 1000));
queue.put(proct);// 放進去一個
System.out.println("放在 --> " + this.queue.size());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

class BQConsume implements Runnable {
private BlockingQueue<Integer> queue;

public BQConsume(BlockingQueue<Integer> queue) {
this.queue = queue;
}

public void run() {
for (int i = 1; i <= 10; i++) {
try {
while(queue.isEmpty()) {
Thread.sleep(1000);
}
Thread.sleep((int) (Math.random() * 1000));
System.out.println("拿出 <-- " + this.queue.size());
queue.take();// 拿出來一個
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
執行結果:
放在 --> 1
放在 --> 2
拿出 <-- 2
拿出 <-- 1
放在 --> 1
拿出 <-- 1
放在 --> 1
放在 --> 2
拿出 <-- 2
放在 --> 2
放在 --> 3
拿出 <-- 3
拿出 <-- 2
放在 --> 2
放在 --> 3
拿出 <-- 3
放在 --> 3
拿出 <-- 3
拿出 <-- 2
拿出 <-- 1

B. 用Java實現了一個生產者消費者問題,但是當有多個生產者消費者時,會發生死鎖,不知怎麼切解決

可以在生產的方法里給線程,這樣就不會死鎖了

C. java啟用另外一個線程設置無超時狀態

Java的線程是不允許啟動兩次的,第二次調用必然會拋出IllegalThreadStateException,這是一種運行時異常,多次調用start被認為是編程錯誤。

關於線程生命周期的不同狀態,在Java 5以後,線程狀態被明確定義在其公共內部枚舉類型java.lang.Thread.State中,分別是:

新建(NEW),表示線程被創建出來還沒真正啟動的狀態,可以認為它是個Java內部狀態。
就緒(RUNNABLE),表示該線程已經在JVM中執行,當然由於執行需要計算資源,它可能是正在運行,也可能還在等待系統分配給它CPU片段,在就緒隊列裡面排隊。 在其他一些分析中,會額外區分一種狀態鏈弊RUNNING,但是從Java API的角度,並不能表示出來。
阻塞(BLOCKED),這個狀態和我們前面兩講介紹的同步非常相關,阻塞表示線程在等待Monitor lock。比如,線程試圖通過synchronized去獲取某個鎖,但是其他線程已經獨佔了,那麼當前線程就會處於阻塞狀態。
等待(WAITING),表示正在等待其他線程採取某些操作。一個常見的場景是類似生產者消費者模式,發現任務條件尚未滿足,就讓當前消費者線程等待(wait),另外的生產者線程去准備任務數據,然後通過類似notify等動作,通知消費線程可以繼續工作了。Thread.join()也會令線程進入等待狀態。
計時等待(TIMED_WAIT),其進入條件和等待狀態類似,但是調用的是存在超時條件的方法,比如wait或join等方法的指定超時版本,如下面示例:
public final native void wait(long timeout) throws InterruptedException;

終止(TERMINATED),不管是意外退出還是正常執行結束,線程已經完成使命,終止運行,也有人把這個狀態叫作死亡。
在第二次調用start()方法的時候,線程可能處於終止或者其他(非NEW)狀態,但是不論如何,都是不可凱絕以再次啟動的。

考點分析

今天的問題可以算是個常見的面試熱身題目,前面的給出的典型回答,算是對基本狀態和簡單流轉的一個介紹,如果覺得還不夠直觀,我在下面分析會對比一個狀態圖進行介紹。總的來說,理解線程對於我們日常開發或者診斷分析,都是不可或缺的基礎。

面試棚孫族官可能會以此為契機,從各種不同角度考察你對線程的掌握:

相對理論一些的面試官可以會問你線程到底是什麼以及Java底層實現方式。
線程狀態的切換,以及和鎖等並發工具類的互動。
線程編程時容易踩的坑與建議等。
可以看出,僅僅是一個線程,就有非常多的內容需要掌握。我們選擇重點內容,開始進入詳細分析。

知識擴展

首先,我們來整體看一下線程是什麼?

從操作系統的角度,可以簡單認為,線程是系統調度的最小單元,一個進程可以包含多個線程,作為任務的真正運作者,有自己的棧(Stack)、寄存器(Register)、本地存儲(Thread Local)等,但是會和進程內其他線程共享文件描述符、虛擬地址空間等。

在具體實現中,線程還分為內核線程、用戶線程,Java的線程實現其實是與虛擬機相關的。對於我們最熟悉的Sun/Oracle JDK,其線程也經歷了一個演進過程,基本上在Java 1.2之後,JDK已經拋棄了所謂的Green Thread,也就是用戶調度的線程,現在的模型是一對一映射到操作系統內核線程。

如果我們來看Thread的源碼,你會發現其基本操作邏輯大都是以JNI形式調用的本地代碼。

D. JAVA模擬生產者與消費者實例

使用的生產者和消費者模型具有如下特點:
(1)本實驗的多個緩沖區不是環形循環的,也不要求按順序訪問。生產者可以把產品放到目前某一個空緩沖區中。
(2)消費者只消費指定生產者的產品。
(3)在測試用例文件中指定了所有的生產和消費的需求,只有當共享緩沖區的數據滿足了所有關於它的消費需求後,此共享緩沖區才可以作為空閑空間允許新的生產者使用。
(4)本實驗在為生產者分配緩沖區時各生產者間必須互斥,此後各個生產者的具體生產活動可以並發。而消費者之間只有在對同一產品進行消費時才需要互斥,同時它們在消費過程結束時需要判斷該消費對象是否已經消費完畢並清除該產品。
Windows
用來實現同步和互斥的實體。在Windows
中,常見的同步對象有:信號量(Semaphore)、
互斥量(Mutex)、臨界段(CriticalSection)和事件(Event)等。本程序中用到了前三個。使用這些對象都分
為三個步驟,一是創建或者初始化:接著請求該同步對象,隨即進入臨界區,這一步對應於互斥量的
上鎖;最後釋放該同步對象,這對應於互斥量的解鎖。這些同步對象在一個線程中創建,在其他線程
中都可以使用,從而實現同步互斥。當然,在進程間使用這些同步對象實現同步的方法是類似的。
1.用鎖操作原語實現互斥
為解決進程互斥進人臨界區的問題,可為每類臨界區設置一把鎖,該鎖有打開和關閉兩種狀態,進程執行臨界區程序的操作按下列步驟進行:
①關鎖。先檢查鎖的狀態,如為關閉狀態,則等待其打開;如已打開了,則將其關閉,繼續執行步驟②的操作。
②執行臨界區程序。
③開鎖。將鎖打開,退出臨界區。
2.信號量及WAIT,SIGNAL操作原語
信號量的初值可以由系統根據資源情況和使用需要來確定。在初始條件下信號量的指針項可以置為0,表示隊列為空。信號量在使用過程中它的值是可變的,但只能由WAIT,SIGNAL操作來改變。設信號量為S,對S的WAIT操作記為WAIT(S),對它的SIGNAL操作記為SIGNAL(S)。
WAIT(S):順序執行以下兩個動作:
①信號量的值減1,即S=S-1;
②如果S≥0,則該進程繼續執行;
如果
S(0,則把該進程的狀態置為阻塞態,把相應的WAITCB連人該信號量隊列的末尾,並放棄處理機,進行等待(直至其它進程在S上執行SIGNAL操作,把它釋放出來為止)。
SIGNAL(S):順序執行以下兩個動作
①S值加
1,即
S=S+1;
②如果S)0,則該進程繼續運行;
如果S(0則釋放信號量隊列上的第一個PCB(既信號量指針項所指向的PCB)所對應的進程(把阻塞態改為就緒態),執行SIGNAL操作的進程繼續運行。
在具體實現時注意,WAIT,SIGNAL操作都應作為一個整體實施,不允許分割或相互穿插執行。也就是說,WAIT,SIGNAL操作各自都好像對應一條指令,需要不間斷地做下去,否則會造成混亂。
從物理概念上講,信號量S)時,S值表示可用資源的數量。執行一次WAIT操作意味著請求分配一個單位資源,因此S值減1;當S<0時,表示已無可用資源,請求者必須等待別的進程釋放了該類資源,它才能運行下去。所以它要排隊。而執行一次SIGNAL操作意味著釋放一個單位資源,因此S值加1;若S(0時,表示有某些進程正在等待該資源,因而要把隊列頭上的進程喚醒,釋放資源的進程總是可以運行下去的。
---------------
/**
*
生產者
*
*/
public
class
Procer
implements
Runnable{
private
Semaphore
mutex,full,empty;
private
Buffer
buf;
String
name;
public
Procer(String
name,Semaphore
mutex,Semaphore
full,Semaphore
empty,Buffer
buf){
this.mutex
=
mutex;
this.full
=
full;
this.empty
=
empty;
this.buf
=
buf;
this.name
=
name;
}
public
void
run(){
while(true){
empty.p();
mutex.p();
System.out.println(name+"
inserts
a
new
proct
into
"+buf.nextEmptyIndex);
buf.nextEmptyIndex
=
(buf.nextEmptyIndex+1)%buf.size;
mutex.v();
full.v();
try
{
Thread.sleep(1000);
}
catch
(InterruptedException
e)
{
e.printStackTrace();
}
}
}
}
---------------
/**
*
消費者
*
*/
public
class
Customer
implements
Runnable{
private
Semaphore
mutex,full,empty;
private
Buffer
buf;
String
name;
public
Customer(String
name,Semaphore
mutex,Semaphore
full,Semaphore
empty,Buffer
buf){
this.mutex
=
mutex;
this.full
=
full;
this.empty
=
empty;
this.buf
=
buf;
this.name
=
name;
}
public
void
run(){
while(true){
full.p();
mutex.p();
System.out.println(name+"
gets
a
proct
from
"+buf.nextFullIndex);
buf.nextFullIndex
=
(buf.nextFullIndex+1)%buf.size;
mutex.v();
empty.v();
try
{
Thread.sleep(1000);
}
catch
(InterruptedException
e)
{
e.printStackTrace();
}
}
}
}
-------------------------
/**
*
緩沖區
*
*/
public
class
Buffer{
public
Buffer(int
size,int
nextEmpty,int
nextFull){
this.nextEmptyIndex
=
nextEmpty;
this.nextFullIndex
=
nextFull;
this.size
=
size;
}
public
int
size;
public
int
nextEmptyIndex;
public
int
nextFullIndex;
}
-----------------
/**
*
此類用來模擬信號量
*
*/
public
class
Semaphore{
private
int
semValue;
public
Semaphore(int
semValue){
this.semValue
=
semValue;
}
public
synchronized
void
p(){
semValue--;
if(semValue<0){
try
{
this.wait();
}
catch
(InterruptedException
e)
{
e.printStackTrace();
}
}
}
public
synchronized
void
v(){
semValue++;
if(semValue<=0){
this.notify();
}
}
}
------------------------
public
class
Test
extends
Thread
{
public
static
void
main(String[]
args)
{
Buffer
bf=new
Buffer(10,0,0);
Semaphore
mutex=new
Semaphore(1);
Semaphore
full=new
Semaphore(0);
Semaphore
empty=new
Semaphore(10);
//new
Thread(new
Procer("p001",mutex,full,empty,bf)).start();
Procer
p=new
Procer("p001",mutex,full,empty,bf);
new
Thread(new
Procer("p002",mutex,full,empty,bf)).start();
new
Thread(new
Procer("p003",mutex,full,empty,bf)).start();
new
Thread(new
Procer("p004",mutex,full,empty,bf)).start();
new
Thread(new
Procer("p005",mutex,full,empty,bf)).start();
try{
sleep(3000);
}
catch(Exception
ex)
{
ex.printStackTrace();
}
new
Thread(new
Customer("c001",mutex,full,empty,bf)).start();
new
Thread(new
Customer("c002",mutex,full,empty,bf)).start();
new
Thread(new
Customer("c003",mutex,full,empty,bf)).start();
new
Thread(new
Customer("c004",mutex,full,empty,bf)).start();
new
Thread(new
Customer("c005",mutex,full,empty,bf)).start();
}
}
--------------------------------------------

E. JAVA怎麼編多個生產者多個消費者代碼啊

publicclassProceConsumerDemo{

publicstaticvoidmain(String[]args){
//1.創建資源
Resourceresource=newResource();
//2.創建兩個任務
Procerprocer=newProcer(resource);
Consumerconsumer=newConsumer(resource);
//3.創建線程磨告
/*
*多生產多消費產生的問題:重復生產、重復消費
*/
Threadthread0=newThread(procer);
Threadthread1=newThread(procer);

thread0.setName("生產者(NO0)");
thread1.setName("生產者(NO1)");

Threadthread2=newThread(consumer);
Threadthread3=newThread(consumer);

thread2.setName("消費者(NO2)");
thread3.setName("消費者(NO3)");

thread0.start();
thread1.start();
thread2.start();
thread3.start();
}
}

classResource{
privateStringname;
privateintcount=1;
//定義標記
privatebooleanflag;

//提供給商品賦值的方法
publicsynchronizedvoidsetName(Stringname){//thread0,thread1在這里運行
while(flag)//判斷標記為true,執行wait等待,為false則生產
/*
*這里使用while,而不使用if的理由如下:
*
*thread0有可能第二次也搶到鎖的執行權,判斷為真,則有麵包不生產,所以接下來執行等待,此時thread0在線程池中。
*接下來活的線程有3個(除了thread0),這三個線程都有可能獲取到執行權.
*假設thread1獲得了執行權,判斷為真,則有麵包不生產,執行等待。此時thread1又進入到了線程池中。
*接下來有兩個活的線程thread2和thread3。假設thread2又搶到了執行權,所以程序轉到了消費get處……
*/
try{
this.wait();//這里wait語句必須包含在try/catch塊中,拋出異常。
}catch(InterruptedExceptione){
e.printStackTrace();
}
this.name=name+count;//第一個麵包
count++;//2
System.out.println(Thread.currentThread().getName()+this.name);//thread0線程生產了麵包1

//生產完畢,將標記改成true.
flag=true;//thread0第一次生產完麵包以後,將標記改為真,表示滑大有麵包了

//喚醒消費者(這里使用notifyAll而不使用notify的原因在下面)

this.notifyAll();//第一次在這里是空喚醒,沒有意義
}

/*
*通過同步,解決了沒生產就消費的問題
*生產完以後,生產者釋放了this鎖,此時,生產者和消費者同時去搶鎖,又是生產者搶到了鎖,所以就出現了一直生產的情況。
*與「生產一個就消費一個的需求不符合」等待喚醒機制wait();該方法可以使線程處於凍結狀態,並將線程臨時存儲到線程池
*notify();喚醒指定線程池中的任意一個線程。notifyAll();喚醒指定線程池中的所有線程
*這些方法必須使用在同步函數中,因為他們用來操作同步鎖上的線程上的狀態的。
*在使用這些方法時候,必須標識他們瞎讓明所屬於的鎖,標識方式就是鎖對象.wait();鎖對象.notify();鎖對象.notifyAll();
*相同鎖的notify()可以獲取相同鎖的wait();
*/

publicsynchronizedvoidgetName(){//thread2,thread3在這里運行
while(!flag)
/*
*……接著上面的程序執行分析thread2拿到鎖獲取執行權之後,判斷!flag為假,則不等待,直接消費麵包1,輸出一次.
*消費完成之後將flag改為假接下來又喚醒了thread0或者thread1生產者中的一個
*假設又喚醒了thread0線程,現在活的線程有thread0,thread2,thread3三個線程
*假設接下來thread2又搶到了執行權,判斷!flag為真,沒麵包了,停止消費,所以thread2執行等待.
*此時活著的線程有thread0和thread3。
*假設thread3得到了執行權,拿到鎖之後進來執行等待,此時活著的線程只有thread0.
*所以thread0隻能搶到執行權之後,生產麵包2,將標記改為true告訴消費者有麵包可以消費了。
*接下來執行notify喚醒,此時喚醒休眠中的3個線程中的任何一個都有可能。
*如果喚醒了消費者thread2或者thread3中的任何一個,程序都是正常。如果此時喚醒thread1則不正常。
*如果喚醒了thread1,此時活著的線程有thread0和thread1兩個線程。
*假設thread0又獲得了執行權,判讀為真有麵包,則又一次執行等待。
*接下來只有thread1線程有執行權(此時沒有判斷標記直接生產了,出錯了),所以又生產了麵包3。在這個過程中,麵包2沒有被消費。
*這就是連續生產和消費容易出現的問題。
*
*原因:被喚醒的線程沒有判斷標記就開始執行了,導致了重復的生產和消費發生。
*
*解決:被喚醒的線程必須判斷標記,使用while循環標記,而不使用if判斷的理由。
*
*但是接下來會出現死鎖,原因在於:
*上面的程序中thread0在執行notify的時候喚醒了thread1,而此時thread2和thread3兩個消費者線程都處於等待狀態
*thread1在執行while判斷語句之後判斷為真,則執行等待,此時所有的線程都處於凍結等待狀態了。
*
*原因:本方線程在執行喚醒的時候又一次喚醒了本方線程,而本方線程循環判斷標記又繼續等待,而導致所有的線程都等待。
*
*解決:本方線程喚醒對方線程,可以使用notifyAll()方法
* 喚醒之後,既有本方,又有對方,但是本方線程判斷標記之後,會繼續等待,這樣就有對方線程在執行。
*/
try{
this.wait();
}catch(InterruptedExceptione){
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+this.name);
//將標記改為false
flag=false;
//喚醒生產者
this.notify();
}
}

//生產者
classProcerimplementsRunnable{
privateResourceresource;

publicProcer(Resourceresource){
this.resource=resource;
}

publicvoidrun(){
while(true){
resource.setName("麵包");
}
}
}

//消費者
{
privateResourceresource;

publicConsumer(Resourceresource){
this.resource=resource;
}

@Override
publicvoidrun(){
while(true){
resource.getName();
}
}
}

F. java多生產者和消費者問題,重復生產消費

我暈看了好久,別人寫的代碼看的真是辛苦,也沒注釋...修改了一堆括弧!!

妥妥的沒問題,你的資源用的數組,換句話說,

你數組被A1線程增加索引1,然後B過來拿走索引1;數組裡面此刻是什麼?當然是0了啊;因為你遞減了...

然後A2被悉銷拿到執行權,怎麼樣?是不是還睜薯游去增加索引1??明白了?

如果你想要不重復,就別遞減就行了!

另外你這么改,有什麼問題看的很手銷醒目,知道發生在哪個線程上!

G. 多線程怎麼用

如何實現多線程
兩種方式:

繼承Thread類,重寫run方法

實現Runnable介面,實現run方法。

啟動線程調用線程的start方法。

如何用多線程來處理一個問題?
每個線程只完成一個數的累積和,(用線程的參數來傳遞指定的數),不要把數組裡面的所有數都進行計算。

你可以傳給線程的時候,除了傳遞輸入輸出數組以外租正讓,再傳遞一個index。線程中只處理這個index位置上的數就可以了。
Java線程怎樣使用?
Thread線程類,該類有一個共有的無返回值不帶參數的run方法。

可以用子類繼承Thread類然後重寫run方法。

class T extends Thread{public void run(){while(true){System.out.println("xx"); } 范 }使用是聲明改自定義類對象,調用start方法啟動線程。

Thread t=new T();t.strat();線程啟動執行類中run方法中預制的代碼。

也可以通過實現線程介面Runnable來創建線程

Thread t=new Thread(new Runnable{public void run(){代碼 }});t.start();
多線程有幾種實現方法
線程建立/執行:

HANDLE Handle1;

DWORD ID1;

Handle1=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Thread1,NULL,0,&ID1);

線程等待:

WaitForSingleObject(Handle1,INFINITE);

線程同步---生產者消費者:

HANDLE m_S_Consumer;

m_S_Consumer = CreateSemaphore(NULL,0,20, NULL);創建,最多允許有20個產品等待使用,初始0個

ReleaseSemaphore(m_S_Consumer,1,NULL);生產1個

if(WaitForSingleObject(m_S_Consumer,INFINITE) == WAIT_OBJECT_0){消費1個

......

}
如何使用線程
java平台從開始就被設計成為多線程環境。在你的主程序執行的時候,其它作業如碎片收集和事件處理則是在後台進行的。本質上,你可以認為這些作業是線程。它們正好是系統治理線程,但是無論如何,它們是線程弊局。線程使你能夠定義相互獨立的作業,彼此之間互不幹擾。系統將交換這些作業進或出CPU,這樣(從外部看來)它們好象是同時運行的。 在你需要在你的程序中處理多個作業時,你也可以使用多個進程。這些進程可以是你自己創建的,你也可以操縱系統線程。 你進行這些多作業處理,要使用幾個不同的類或介面: java.util.Timer類

javax.swing.Timer類Thread類Runnable介面 對於簡單的作業,通常需要重復的,你可以使用java.util.Timer類告訴它「每半秒鍾做一次」。清改注重:大多數系統常式是使用毫秒的。半秒鍾是500毫秒。 你希望Timer實現的任務是在java.util.TimerTask實例中定義的,其中運行的方法包含要執行的任務。這些在Hi類中進行了演示,其中字元串「Hi」重復地被顯示在屏幕上,直到你按Enter鍵。 import java.util.*;

public class Hi {

public static void main(String args[])

throws java.io.IOException {

TimerTask task = new TimerTask() {

public void run() {

System.out.PRintln("Hi");}};Timer timer = new Timer();

timer.schele(task, 0, 500);

System.out.println("Press ENTER to stop");

System.in.read(new byte[10]);

timer.cancel();}} Java Runtime Environment工作的方式是只要有一個線程在運行,程序就不退出。這樣,當取消被調用,沒有其它線程在運行了,則程序退出。有一些系統線程在運行,如碎片收集程序。這些系統線程也被稱為後台線程。後台線程的存在不影響運行環境被關閉,只有非後台線程保證運行環境不被關閉。 Javax.swing.Timer類與java.util.timer類的工作方式相似,但是有一些差別需要注重。第一,運行的作業被ActionListener介面的實現來定義。第二,作業的執行是在事件處理線程內部進行的,而不象java.util.Timer類是在它的外部。這是很重要的,因為它關繫到Swing組件集是如何設計的。 假如你不熟悉Swing,它是一組可以被Java程序使用的圖形組件。Swing被設計程被稱為單線程的。這意味著對Swing類內部內容的訪問必須在單個線程中完成。這個特定的線程是事件處理線程。這樣,例如你想改變Label組件的文字,你不能僅僅調用Jlabel的setText方法。相反,你必須確認setText調用發生在事件處理線程中,而這正是javax.swing.Time類派的上用場的地方。 為了說明這第二種情況,下面的程序顯示一個增加的計數器的值。美半秒鍾計數器的數值增加,並且新的數值被顯示。
C語言如何實現多線程同時運行
使用pthread庫執行多線程,這個是Linux下的線程庫 Windows下應該有自己的API,不過這種東西一般還是以Linux為標准。pthread_create()創建一個線程,傳入fun()的函數指針就行了。

然後這個Beep()的需求要進行線程間通信,可以用共享內存的方法,設一個bool變數flag共享,然後beep的時候設為false,beep完設成true。fun()裡面每次看一下這個flag,是false的話就不做動作等下一秒,基本可以滿足需求。

這樣做的好處是實現簡單,但時間是以1s為單位的。如果要8秒結束立刻執行,需要用條件變數的方法來控制,比較復雜,這樣的實現方式一個可以滿足需求了。
如何在for循環中使用多線程
乾脆把 i 當做參數傳入好了

class Program

{

static int i;

static void Main(string[] args)

{

i = 0;

do

{

new Thread(new ParameterizedThreadStart(s)).Start(i);

i++;

} while (i < 10);

Console.Read();

}

static private void s(object index)

{

Console.WriteLine(Thread.CurrentThread.ManagedThreadId + "," + (int)index);

}

}
如何增加多線程的穩定性
微軟官方給出的方案在MSDN裡面有說,就是使用ActiveX EXE那種"單元線程模型".

我也曾經試過,的確可以實現"多線程",只是由於要多一個EXE,比較麻煩,後來就沒有深入了.

結果一次無意中在VBGOOD中看到一段代碼,才打通了一個關節:為什麼不直接使用ActiveX EXE寫程序呢?!

那段代碼裡面,是直接使用這種工程類型,然後在工程內使用CreateObject來生成一個新對象,這樣的話,新的對象就工作於一個單元線程內了.

其實這個我也知道,可是就沒有想到在ActiveX EXE內部使用

看來思路真的不如人.....還要多多學習,多多積累.

ActiveX EXE工程設置為"獨立啟動"後,貌似只能從Sub Main里進行初始化.

而每個對象的建立,都會調用一次這個過程,因此這個過程需要一次性運行.

但是MSDN里說得很清楚,在單元線程模型裡面,全局變數的范圍只能是本單元,因此不能使用設置全局變數來完成這個過程的一次運行邏輯.

原代碼里使用了GetProp等方式,感覺不是很好,於是作了一下改進,使用事件對象來完成此工作.

Sub Main相關代碼如下:

Private Const MyEvent As String = "m5home"

Dim hEvent As Long

Sub Main()

If GetEventHandle = 0 Then '由於每個新對象的建立,都要執行Main()過程,因此使用事件對象來進行判斷.

hEvent = CreateEvent(0&, False, False, MyEvent) '在單元線程下,模塊里的全局變數已經沒有用了.frmMain.Show

End If

End Sub

Private Function GetEventHandle() As Long

GetEventHandle = OpenEvent(EVENT_ALL_ACCESS, False, MyEvent)

Call CloseHandle(GetEventHandle)

End Function

Public Function Quit()

Call CloseHandle(hEvent)

End Function

Private Const MyEvent As String = "m5home"

Dim hEvent As Long

Sub Main() If GetEventHandle = 0 Then '由於每個新對象的建立,都要執行Main()過程,因此使用事件對象來進行判斷.

hEvent = CreateEvent(0&, False, False, MyEvent) '在單元線程下,模塊里的全局變數已經沒有用了.frmMain.Show

End If

End Sub

Private Function GetEventHandle() As Long GetEventHandle = OpenEvent(EVENT_ALL_ACCESS, False, MyEvent)

Call CloseHandle(GetEventHandle)

End Function

Public Function Quit()

Call CloseHandle(hEvent)

End Function

由於事件對象是系統范圍的,因此可......>>
怎樣用純C寫一個多線程的程序
這是我以前寫的一個多線程範例,湊合看看吧:

#include

#include

#include

using namespace std;

提示計程車到達的條件變數

pthread_cond_t taxiCond;

同步鎖

pthread_mutex_t taxiMutex;

旅客到達等待計程車

void * traveler_arrive(void * name)

{

cout<< " Traveler: " <<(char *)name<< " needs a taxi now! " <

pthread_mutex_lock(&taxiMutex);

pthread_cond_wait (&taxiCond, &taxiMutex);

pthread_mutex_unlock (&taxiMutex);

cout<< " Traveler: " << (char *)name << " now got a taxi! " <

pthread_exit( (void *)0 );

}

計程車到達

void * taxi_arrive(void *name)

{

cout<< " Taxi " <<(char *)name<< " arrives. " <

pthread_cond_signal(&taxiCond);

pthread_exit( (void *)0 );

}

int main()

{

pthread_t thread;

pthread_attr_t threadAttr;

pthread_attr_init(&threadAttr);

pthread_create(&thread, & threadAttr, taxi_arrive, (void *)( " Jack " ));

sleep(1);

pthread_create(&thread, &threadAttr, traveler_arrive, (void *)( " Susan " ));

sleep(1);

pthread_create(&thread, &threadAttr, taxi_arrive, (void *)( " Mike " ));

sleep(1);

return 0;

}...>>
線程是什麼,什麼時候使用線程,如何使用線程?
如果用書面語,那你還不如看書呵,還是通俗點。

線程:

舉例:如果你開著QQ,需要和多人進行語音,那麼,你邀請一位朋友進行連接,就需要開辟一條線程,用於保持連接和傳遞數據。它和進程不同,具體的內容可以網路下:線程和進程的區別。

使用:

一般會在同時觸發多項任務時使用線程,比如伺服器和客戶端的連接,作為伺服器,我需要接受多個客戶端的訪問,每個客戶端的操作又都不一樣,但都需要伺服器去處理,那麼作為伺服器我會創建專屬於該客戶端的一個連接(一個線程去hold住它),通過互相傳遞指令去執行任務。

創建:

有2種方法:

推薦用:

public class TestRun implements Runnable{ 第一步實現Runnable介面

public TestRun(){

new Thread(this).start(); 第三步啟動線程

}

public void run(){ 第二步實現run方法,該方法為介面中抽象方法

System.out.println("線程體");

}

}

熱點內容
pid匯編程序 發布:2024-11-02 08:28:32 瀏覽:323
c語言數組scanf 發布:2024-11-02 08:28:20 瀏覽:784
android文本框居中 發布:2024-11-02 08:21:55 瀏覽:439
撕裂者哪個配置好 發布:2024-11-02 07:58:49 瀏覽:990
c編寫的程序經過編譯 發布:2024-11-02 07:41:18 瀏覽:941
mc伺服器靈魂綁定如何出售 發布:2024-11-02 07:39:36 瀏覽:583
cf伺服器不同如何一起玩游戲 發布:2024-11-02 07:38:24 瀏覽:945
手機壓縮游戲 發布:2024-11-02 07:27:03 瀏覽:451
c語言的四書五經 發布:2024-11-02 07:21:42 瀏覽:742
vbaexcel資料庫 發布:2024-11-02 07:16:09 瀏覽:11