生产者消费者java
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("线程体");
}
}