【问题标题】:Java basic thread pool implementation with locks.ReentrantLock带锁的Java基本线程池实现.ReentrantLock
【发布时间】:2014-04-25 12:12:57
【问题描述】:

我是 Java 新手。我只是在试验线程,我想创建一个线程池之类的东西(如果这实际上是我正在做的......)。

基本上我有一个while循环,它会触发线程,直到仍有任务要执行&&而最大并发线程不大于n。每个线程使用 java.util.concurrent.locks.ReentrantLock 来提供一个锁,围绕任务计数变量在每个线程中减少,线程计数变量在线程开始时增加并在线程结束前减少(代码气味?):

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Test { 
   public static void main(String[] args) {

      //overcome limitation of closure not being able to modify outer variable with arr.
      final int[] runningThreads = {0};
      final int[] taskcount = {10};

      final Lock _mutex = new ReentrantLock(true);

      int maxThreadQty = 3;


      while ((taskcount[0] > 0) && (runningThreads[0] < maxThreadQty))  {

         new Thread("T") {
             public void run() {
                  System.out.println("New Thread Started");
                  _mutex.lock();
                  runningThreads[0]++;
                  System.out.println("Running Threads: " + runningThreads[0]);
                  System.out.println("Times to go: " + taskcount[0]);
                  _mutex.unlock();
                  // actually do something;
                  _mutex.lock();
                  taskcount[0]--;
                  runningThreads[0]--;
                  _mutex.unlock();
             }

          }.start();
      }
   }
}

当我运行代码时,新线程不断被触发,任务数只减少了两到三倍......

最后几行输出(读取时间作为要执行的任务):

Running Threads: 565
Times to go: 8
Running Threads: 566
Times to go: 8
Running Threads: 567
Times to go: 8
Running Threads: 568
Times to go: 8
Running Threads: 569
Times to go: 8
Running Threads: 570
Times to go: 8
Running Threads: 571
Times to go: 8
Running Threads: 572
Times to go: 8
Running Threads: 573
Times to go: 8
Running Threads: 574
Times to go: 8
Running Threads: 575
Times to go: 8

CTRL-C

我确信我使用线程或锁的方式肯定有什么问题。但作为一个 java 新手,我可能会遗漏很多东西(甚至可能是最基本的东西),一些帮助和一些帮助让我回到正确的道路上将不胜感激......! 谢谢。

我将此作为线程的参考:http://tutorials.jenkov.com/java-concurrency/creating-and-starting-threads.html

然后这个stackoverflow回答看看如何使用ReentrantLock:https://stackoverflow.com/a/12510490/988591

这对于闭包无法修改外部变量的解决方法(使用数组值): http://c2.com/cgi/wiki?ClosuresThatWorkAroundFinalLimitation

【问题讨论】:

  • 您正在主线程中创建“子线程”。没有人知道处理器将允许哪个线程执行。这意味着从技术上讲,您的主线程可能会在这些子线程中的任何一个有机会减少计数器之前创建随机数量的新线程。
  • 谢谢,如果您愿意这样做,您愿意连续或两次解释正确实现的工作原理吗?谢谢!

标签: java multithreading concurrency locking reentrantlock


【解决方案1】:

您不能使用built in thread pool 功能吗?

如果不是,问题是runningThreads 在每个线程启动并获得锁之前不会增加。实际上,主线程可能会运行相当长的一段时间,同时无限制地启动新线程。

一种解决方案可能是在启动新线程之前增加主线程上的runningThreads 变量,但在每个工作线程内减少变量。

我不想暗示您的代码的其他所有内容都“很好”(创建一个健壮的线程池实现可能是一项相当困难且涉及的任务),但可以避免该问题的最小更改可能是

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Test { 
   public static void main(String[] args) {

      //overcome limitation of closure not being able to modify outer variable with arr.
      final int[] runningThreads = {0};
      final int[] taskcount = {10};

      final Lock _mutex = new ReentrantLock(true);

      int maxThreadQty = 3;


      while ((taskcount[0] > 0) && (runningThreads[0] < maxThreadQty))  {
         System.out.println("New Thread Started");
         _mutex.lock();
         runningThreads[0]++;
         System.out.println("Running Threads: " + runningThreads[0]);
         System.out.println("Times to go: " + taskcount[0]);
         _mutex.unlock();
         new Thread("T") {
             public void run() {
                  // actually do something;
                  _mutex.lock();
                  taskcount[0]--;
                  runningThreads[0]--;
                  _mutex.unlock();
             }

          }.start();
      }
   }
}

【讨论】:

  • 谢谢!这样代码就可以执行所需数量的任务!但线程数始终为 1:New Thread Started Running Threads: 1 Times to go: 5 New Thread Started Running Threads: 1 Times to go: 4 New Thread Started Running Threads: 1 Times to go: 3 New Thread Started Running Threads: 1 Times to go: 2 New Thread Started Running Threads: 1 Times to go: 1 New Thread Started Running Threads: 1 Times to go: 0 你认为它的行为是什么?
  • @jj_ 你真的在“实际做某事”部分放了什么吗?如果没有,很有可能线程在下一个线程开始之前就结束了。
  • 这可能是因为每个线程实际上持续时间太短以至于它们永远不会重叠......可能吗?我添加了 Thread.sleep(10000) ,然后看起来它们确实加起来直到最大允许线程数!我猜你做到了!谢谢!
  • 是的,我们同时写了这个;)
  • 代码的一个大缺陷是,一旦通过“while”循环达到线程的最大计数,“while”将不再计算为真,因此它将停止循环.. . 所以剩余任务的其他线程将永远不会被执行:)
猜你喜欢
  • 2016-07-24
  • 2011-11-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-07
相关资源
最近更新 更多