2011-11-17 38 views
1

我有多个线程打印数据。所有数据都打印出来;然而,他们不是为了。含义线程2开始打印,而线程1尚未完成,这会导致不一致。我如何保证一致性?含义一旦线程1完成,线程2可以打印。Java - Println不是为了

+0

你想要两个线程同时执行或线程1完成其运行后执行线程2吗? –

+0

线程1完成其运行后执行线程2 –

+5

那么为什么你需要两个线程呢?线程背后的全部想法是同时运行代码。 –

回答

0

从你的意见,你正在寻找实现1 1 1 1 2 2 2 2所以你需要做的实际上是等待线程1完成,然后再启动线程2,是这样的:

Thread1 thread1 = new Thread1(); 
Thread2 thread2 = new Thread2(); 

thread1.start(); 

thread1.join(); // This waits for Thread1 to finish before starting Thread2 
thread2.start(); 

但是,如果你想有两个线程开始,但有线程2等待通过其处理部分的方式,在等待线程1完成 - 这可以通过一些技巧来完成 - 一个特别想到的 - 使用Semaphore.

例子:

好吧,首先确定你的线程构造函数接受一个信号量,从而:

// Thread2 would be identical wrt the semaphore 
public Thread1(Semaphore semaphore) throws InterruptedException 
{ 
    this.semaphore = semaphore; // store semaphore locally 
    semaphore.acquire(2); 
} 

线程1的run方法应该是这样的:

public void run() 
{ 
    // .... processing... 

    // ... print stuff 
    System.out.println("1 1 1 1"); 
    semaphore.release(); // release 1 permit, allowing thread2 to continue 

    // ... more processing 

    semaphore.release(); // release last permit. 
} 

线程2的run方法看起来应该类似于此:

public void run() 
{ 
    int permits = 2; 
    try 
    { 
    // .... processing... 

    semaphore.acquire(1); // acquire one more permit (will block until Thread1 releases one) 
    permits++; 

    // ... print stuff 
    System.out.println("2 2 2 2"); 

    // ... more processing  
    } 
    catch (InterruptedException ie) 
    { 
    // interrupted 
    } 

    semaphore.release(permits); // release permits. 
} 

现在,设置线程可以这样完成:

try 
{ 
    Semaphore semaphore = new Semaphore(4); // 4 permit semaphore 

    Thread1 thread1 = new Thread1(semaphore); 
    Thread2 thread2 = new Thread2(semaphore); 

    thread1.start(); 
    thread2.start(); 

    semaphore.acquire(4); 
} 
catch (InterruptedException ie) 
{ 
    // interrupt logic... 
} 
+0

你能举个例子吗?谢谢。 –

+0

如果你只是一次只运行一个线程,为什么还要有线程呢? –

+0

信号量方法将允许两个线程同时执行处理,但允许一个线程中途暂停,允许其他线程继续处理,然后再恢复自己...现在正在编写示例... – Crollster

0

这是线程是如何工作的。如果你启动两个线程它就会像这样1 2 1 2 1 2 1 2

+0

是的,这是事实。我想实现1 1 1 1 2 2 2 2 –

+0

不,它不会。订单没有保证。 –

0

一旦run方法在一个线程已经完成调用它的东西在线程2让它知道它可以打印

0

我们无法计算线程何时运行并完成执行。它完全取决于CPU。你可以做的是在第一个线程结束时将一个标志变量更新为一个值,并在第二个线程执行之前检查该值。

0

你必须保存线程2输出并打印它,直到线程1为止。按照建议的顺序执行它们也会起作用,但那么为什么要使用Thread?

1

如果您希望线程1执行的代码在运行线程2之前完成,那么您不需要线程。您可能想看看Java的ExecutorService。具体而言,Executors. newSingleThreadExecutor()。这将允许您安排任务在另一个线程中运行,但要确保它们按顺序运行。

1

所以,这里是你想要做的(伪代码)是什么:

String results[2]; 

Thread1 thread1 = new Thread1() { 
    public void run() { 
     // do stuff; collect output 
     results[0] = output 
    } 
}; 

Thread2 thread1 = new Thread1() { 
    public void run() { 
     // do stuff; collect output 
     results[1] = output 
    } 
}; 

thread1.start(); 
thread2.start(); 

thread1.join(); 
thread2.join(); 

print result[0]; 
print result[1]; 

上面有利用java.util.concurrent类做的更好的方法,但是这应该给你一个想法

+0

只有数据输出被串行化,而不是主要处理。所以你可能仍然会赢得胜利(当然,这取决于运行方法内部发生了什么)。 –

+0

对不起 - 评论不好的帖子! –

-1

您不能随机从多个线程打印,并预计任何命令。

如果你需要按照有序的方式输出,那么你将不得不同步这些线程(从而破坏具有多个线程的目的),或者让线程回传信息以便输出回主线程它可以处理订购和输出它。

编辑:因为我很无聊。

如果你想通过线程并行化一些工作然后输出结果,你需要让线程将他们工作的产品传回给主线程并让它做输出。一种方法,这是使用队列(这是简单的例子,它依赖线程顺序 - 你可能需要把所有的结果和关联/排序/等):

public class Worker implements Runnable 
{ 

    private ConcurrentLinkedQueue<Integer> outputQueue; 

    public Worker(ConcurrentLinkedQueue<Integer> outputQueue) 
    { 
     this.outputQueue = outputQueue; 
    } 

    @Override 
    public void run() 
    { 

     // Do whatever it is you're doing 
     ... 
     // place result on queue 
     outputQueue.add(result); 

    } 

} 

public class Main 
{ 

    static void main(String[] args) 
    { 

     ArrayList<ConcurrentLinkedQueue<Integer>> myQueues = 
      new ArrayList<ConcurrentLinkedQueue<Integer>>(); 

     Thread[] myThreads = new Thread[numThreads]; 

     // Create queue, create thread with Worker(queue), 
     // start thread 
     for (int i = 0; i < numThreads; i++) 
     { 
      ConcurrentLinkedQueue<Integer> queue = 
       new ConcurrentLinkedQueue<Integer>(); 

      myQueues.add(queue);   

      myThreads[i] = new Thread(new Worker(queue)).start(); 

     } 

     // Wait for all threads to finish, print their results 
     for (int i = 0; i < numThreads; i++) 
     { 
      join(myThreads[i]); 

      // Get the queue for the thread we just joined, 
      // pull off each result and output 
      Integer j; 
      while ((j = myQueues.get(i).poll()) != null) 
      { 
       System.out.println(j); 
      } 

     } 
    } 
} 

这关的。上面有我头,但这是一般的方法