java多线程问题,求助大佬解答,如图

MAFT 2020-09-08 09:06:45

请问大佬,为什么我的程序里多线程往list里加数据,结果会少。。
...全文
2189 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
你这是异步线程,使用同步线程就好了。哈哈。
冰思雨 2020-09-15
  • 打赏
  • 举报
回复
    public static List<String> list = Collections.synchronizedList(new ArrayList<>());

    private static class Task implements Runnable {
        private String string;

        public Task(String string) {
            this.string = string;
        }

        @Override
        public void run() {
            list.add(string);
        }
    }

    public static void main(String[] args) {
        int count = 1000 * 10000;
        int poolSize = 10;
        ExecutorService pool = new ThreadPoolExecutor(poolSize,poolSize, 0L, TimeUnit.MILLISECONDS, new SynchronousQueue(), new ThreadPoolExecutor.CallerRunsPolicy());
        for (int i=0; i< count; i++) {
            Task task = new Task("a string : \t" + i);
            pool.execute(task);
        }

        pool.shutdown();
        System.out.println(list.size());
    }
此代码不推荐
冰思雨 2020-09-15
  • 打赏
  • 举报
回复
public static List<String> list = Collections.synchronizedList(new ArrayList<>());

    private static class Task implements Runnable {
        private CountDownLatch countDownLatch;
        private String string;

        public Task(CountDownLatch countDownLatch, String string) {
            this.countDownLatch = countDownLatch;
            this.string = string;
        }

        @Override
        public void run() {
            try {
                list.add(string);
            } finally {
                countDownLatch.countDown();
            }
        }
    }

    public static void main(String[] args) {
        int count = 1000 * 10000;
        ExecutorService pool = Executors.newFixedThreadPool(10);
        CountDownLatch countDownLatch = new CountDownLatch(count);
        for (int i=0; i< count; i++) {
            Task task = new Task(countDownLatch, "a string : \t" + i);
            pool.submit(task);
        }

        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        pool.shutdown();
        System.out.println(list.size());
    }
冰思雨 2020-09-15
  • 打赏
  • 举报
回复
引用 楼主 MAFT 的回复:
请问大佬,为什么我的程序里多线程往list里加数据,结果会少。。
程序思路没什么问题,问题的关键是,楼主声明的县城里面,是有一个队列的。 shutdown 函数是会保证每个提交的任务都能够正常的处理完毕,但是,当你调用 shutdown 函数的时候,线程池就不会处理 队列 里面的任务了。 楼主你尝试在创建线程池对象的时候,选择 SynchronizedQueue 来试试,虽然没有任务的缓冲功能了,但是,数据最终是一致了。 当然,这不是最佳的解决方案,这种场景,一般使用 CountDownLatch 进行处理,任务里面进行 countDown ,主线程使用 await 等待所有任务都执行完成之后,在进行后续的处理。
qq_39936465 2020-09-09
  • 打赏
  • 举报
回复
楼主的程序main线程结束先于线程池中的线程结束,所以得到的不是最终结果。
qq_39936465 2020-09-09
  • 打赏
  • 举报
回复
shutdown本身不会直接线程池关闭,会等待线程全部完成后才会关闭,shutdownnow会立即关闭线程池,但是main在执行完shutdown后面的打印语句时候,线程池内线程并没有结束,所以打印的结果不是最终结果。
「已注销」 2020-09-09
  • 打赏
  • 举报
回复
需要waitfinish,否则直接关闭线程池,任务可能没有执行完
程序yang 2020-09-09
  • 打赏
  • 举报
回复
楼上大佬说的对
qq_39936465 2020-09-09
  • 打赏
  • 举报
回复
引用 楼主 MAFT 的回复:
请问大佬,为什么我的程序里多线程往list里加数据,结果会少。。

public static void main(String[] args) {
		// TODO Auto-generated method stub
		ExecutorService service=Executors.newFixedThreadPool(50);
		for(int i=0;i<1000*10000;i++) {
			Task task=new Task("a string:"+" "+i);
			service.execute(task);
		}
		service.shutdown();
		while(!service.isTerminated()){};
		System.out.println(list.size());
	}
rumlee 2020-09-09
  • 打赏
  • 举报
回复
子线程没有执行结束,主线程先结束了,所以打印的数字当然就会少了。
yezhijie1 2020-09-09
  • 打赏
  • 举报
回复
引用 6 楼 qq_39936465 的回复:
shutdown本身不会直接线程池关闭,会等待线程全部完成后才会关闭,shutdownnow会立即关闭线程池,但是main在执行完shutdown后面的打印语句时候,线程池内线程并没有结束,所以打印的结果不是最终结果。
我认为6楼说的对
KeepSayingNo 2020-09-09
  • 打赏
  • 举报
回复
你用main方法测试,main方法一结束就直接整个进程都停了。你要么是让主线程一直保持住,每个几秒钟休眠下。或者你用springboot拉起一个进程
鸡窝里的毛 2020-09-08
  • 打赏
  • 举报
回复
shutdown之前,要先waitfinish.

62,628

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧