下面是网上看到的一个java自带的线程池的使用例子。运行结果在后面,结果显示有几个线程放置后未运行,我在自己的程序中使用java自带线程池,也有问题,也有多个线程内容重复的问题。不知这是为什么。
public class TestThreadPool {    private static int produceTaskSleepTime = 2;
    private static int produceTaskMaxNumber = 10;    public static void main(String[] args) {
//构造一个线程池
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2, 4, 3, TimeUnit.SECONDS,
                new ArrayBlockingQueue<Runnable>(3),
                new ThreadPoolExecutor.DiscardOldestPolicy());        for (int i = 1; i <= produceTaskMaxNumber; i++) {
            try {
                //产生一个任务,并将其加入到线程池
                String task = "task@ " + i;
                System.out.println("放置 " + task);
                threadPool.execute(new ThreadPoolTask(task));
                //便于观察,等待一段时间
                Thread.sleep(produceTaskSleepTime);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}class ThreadPoolTask implements Runnable, Serializable {    private static int consuskSleepTime = 2000;
    private static final long serialVersionUID = 0;
    //保存任务所需要的数据
    private Object threadPoolTaskData;    ThreadPoolTask(Object tasks) {
        this.threadPoolTaskData = tasks;
    }    @Override
    public void run() {
        System.out.println("开始 .." + threadPoolTaskData);
        try {
            ////便于观察,等待一段时间
            Thread.sleep(consuskSleepTime);
        } catch (Exception e) {
            e.printStackTrace();
        }
        threadPoolTaskData = null;
    }    public Object getTask() {
        return this.threadPoolTaskData;
    }
}
run:
放置 task@ 1
开始 ..task@ 1
放置 task@ 2
开始 ..task@ 2
放置 task@ 3
放置 task@ 4
放置 task@ 5
放置 task@ 6
开始 ..task@ 6
放置 task@ 7
开始 ..task@ 7
放置 task@ 8
放置 task@ 9
放置 task@ 10
开始 ..task@ 8
开始 ..task@ 9
开始 ..task@ 10
成功生成(总时间:8 秒)

解决方案 »

  1.   

    楼主ThreadPoolExecutor的构造有问题,new ThreadPoolExecutor(2, 4, 3, TimeUnit.SECONDS,
    第二个参数表示线程池最大值,你设定成4表示最大就是4个,如果超过这个数量就是按照 new ThreadPoolExecutor.DiscardOldestPolicy()来处理,结果task3,4等被丢弃了十个任务可以用 new ThreadPoolExecutor(2, 10, 3, TimeUnit.SECONDS 可保证所有的任务被执行
      

  2.   

    楼主后面指定DiscardOldestPolicy 表示删除最老的,3,4是最老的
    你用DiscardPolicy 就不会删除3,4而是后面的
      

  3.   

    发现是队列大小的问题。搞不清队列大小和线程池最大大小(第二个参数)是什么关系呢?
    ghchen:没有办法让它超出时暂停接受新任务而不是删除旧任务?
      

  4.   

    队列大小与线程池最大大小(第二个参数)没有什么特别的关系,ThreadPoolExecutor 执行的任务数是由队列大小与线程池最大大小(第二个参数)这两个数之和确定的,如果你不改线程池最大大小(第二个参数)这个参数的话,可以用LinkedBlockingQueue来代替ArrayBlockingQueue队列,可以得到一个Integer.MAX_VALUE大的队列,这样一般不会有大小的限制
      

  5.   

    ghchen:你是说用LinkedBlockingQueue的话,不管定义的时候定义的是多大,使用的时候如果不够都会自动扩充?另外,经过试验我发现,决定能容纳多少线程的是队列大小,而线程池最大大小简直没什么用
      

  6.   

    我自己写的一个实验程序总是出现多个线程内容相同,可明明赋值的时候都是不同的:public class t {    public static void main(String args[]) throws Exception {
            List<String> list = new ArrayList();
            list.add("aaa");
            list.add("bbb");
            list.add("ccc");
            list.add("ddd");
            list.add("eee");
            list.add("fff");
            list.add("ggg");
            list.add("hhh");
            list.add("iii");
            list.add("jjj");
            System.out.println("\n=================\n");
            System.out.println(list.toString());
            System.out.println("\n=================\n");
            ThreadPoolExecutor threadPool = new ThreadPoolExecutor(5, 7, 2, TimeUnit.SECONDS,
                    new ArrayBlockingQueue<Runnable>(10),
                    new ThreadPoolExecutor.DiscardOldestPolicy());
            for (int i=0; i<list.size(); i++) {
                String link = (list.get(i)).toString();
            System.out.println("\n=*==*==*==*==*==*==*=>" + link);
                threadPool.execute(new one(link));
            }
        }
    }public class one implements Runnable {
        private static String url;    public one(String s_url) {
            url = s_url;
        }
        @Override
        public void run() {
            try {
                System.out.println("\n########" + url + "\n");
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }}运行结果:
    =================[aaa, bbb, ccc, ddd, eee, fff, ggg, hhh, iii, jjj]=================
    =*==*==*==*==*==*==*=>aaa=*==*==*==*==*==*==*=>bbb########bbb
    =*==*==*==*==*==*==*=>ccc=*==*==*==*==*==*==*=>ddd########ddd
    =*==*==*==*==*==*==*=>eee=*==*==*==*==*==*==*=>fff########fff
    ########fff
    =*==*==*==*==*==*==*=>ggg########ggg
    =*==*==*==*==*==*==*=>hhh=*==*==*==*==*==*==*=>iii=*==*==*==*==*==*==*=>jjj########jjj
    ########jjj
    ########jjj
    ########jjj
    ########jjj
      

  7.   


    LinkedBlockingQueue 如果不设置大小(LinkedBlockingQueue())才会保存任意多个任务,如果设置大小就是固定的线程大小肯定是有用的,就说楼主的例子,如果队列大小是3 ,把线程池最大设置成大于7的话,十个任务就一定全部执行,如果小于6的话就会可能像你的结果那样一些任务没有执行到
      

  8.   

    关于你的重复结果 请把  private static String url;这句中的static 删除
      

  9.   

    多谢!最后还有个疑问:刚那个程序怎么总是不能运行完自己结束,非要手工中止?我用的Netbeans
      

  10.   

    我试运行了你的程序,好像与队列大小有关,具体原因我也不清楚,加句threadPool.allowCoreThreadTimeOut(true)后,程序可以自动关闭