java线程池submit与execute的区别

本文通过一个具体的Java代码示例介绍了ReadWriteLock的使用方法及其与ExecutorService的结合应用。探讨了不同线程如何进行读写操作,并分析了在使用ExecutorService时submit与execute方法的区别,特别是对于异常处理的不同之处。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、例子代码,可以先忽略ReadWriteLock相关代码,重点看ExecutorService 就行。

public class ReadWriteLockTest {
	//private static Lock lock = new ReentrantLock();
	private static ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
	private static Lock readLock = readWriteLock.readLock();
	private static Lock writeLock = readWriteLock.writeLock();

	private static int number = 0;

	public void read(Lock lock) {
		lock.lock();
		try {
			Thread.sleep(1000L);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("读线程" + Thread.currentThread() + "--" + number);
		lock.unlock();
		throw new RuntimeException();
	}

	public void write(Lock lock, int value) {
		lock.lock();
		try {
			Thread.sleep(1000L);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		number = value;
		System.out.println("写线程" + Thread.currentThread() + "--" + number);
		lock.unlock();
	}

	public static void main(String[] args) {
		ExecutorService executor = Executors.newFixedThreadPool(50);
		// executor.execute(new Runnable() {
		//
		// public void run() {
		// new ReadWriteLockTest().read(readLock);
		// //new ReadWriteLockTest().read(lock);
		// }
		// });
		//

		// Future future = executor.submit(new Runnable() {
		//
		// public void run() {
		// new ReadWriteLockTest().read(readLock);
		// //new ReadWriteLockTest().read(lock);
		// }
		// });
		// try {
		// future.get();
		// } catch (InterruptedException e) {
		// // TODO Auto-generated catch block
		// e.printStackTrace();
		// } catch (ExecutionException e) {
		// // TODO Auto-generated catch block
		// e.printStackTrace();
		// }


		for (int i = 0; i < 20; i++) {
			executor.submit(new Runnable() {

				public void run() {
					new ReadWriteLockTest().read(readLock);
					// new ReadWriteLockTest().read(lock);
				}
			});
			executor.submit(new Runnable() {

				public void run() {
					new ReadWriteLockTest().write(writeLock, new Random().nextInt());
					// new ReadWriteLockTest().write(lock, new Random().nextInt());
				}
			});
		}


		// for (int i = 0; i < 20; i++) {
		// new Thread(new Runnable() {
		//
		// public void run() {
		// new ReadWriteLockTest().write(writeLock, new Random().nextInt());
		// //new ReadWriteLockTest().write(lock, new Random().nextInt());
		// }
		// }).start();
		// }
		// for (int i = 0; i < 20; i++) {
		// new Thread(new Runnable() {
		//
		// public void run() {
		// new ReadWriteLockTest().read(readLock);
		// // new ReadWriteLockTest().read(lock);
		// }
		// }).start();
		// }
	}
}

ExecutorService.execute方法代码如下:

    public void execute(Runnable command) {
            if (command == null)
                throw new NullPointerException();
                
            int c = ctl.get();
            if (workerCountOf(c) < corePoolSize) {
                if (addWorker(command, true))
                    return;
                c = ctl.get();
            }
            if (isRunning(c) && workQueue.offer(command)) {
                int recheck = ctl.get();
                if (! isRunning(recheck) && remove(command))
                    reject(command);
                else if (workerCountOf(recheck) == 0)
                    addWorker(null, false);
            }
            else if (!addWorker(command, false))
                reject(command);
        }

如果提交的任务不需要一个结果的话直接用execute()会提升很多性能。

protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
    return new FutureTask<T>(runnable, value);
}

protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
    return new FutureTask<T>(callable);
}

包装成FutureTask,当执行到run方法时,我们为何没有看到有Exception抛出来?真相在此,一个try–catch吞噬了所有异常:

public void run() {
        if (state != NEW ||
            !UNSAFE.compareAndSwapObject(this, runnerOffset,
                                         null, Thread.currentThread()))
            return;
        try {
            Callable<V> c = callable;
            if (c != null && state == NEW) {
                V result;
                boolean ran;
                try {
                    result = c.call();
                    ran = true;
                } catch (Throwable ex) {
                    result = null;
                    ran = false;
                    setException(ex);
                }
                if (ran)
                    set(result);
            }
        } finally {
            runner = null;
            int s = state;
            if (s >= INTERRUPTING)
                handlePossibleCancellationInterrupt(s);
        }
    }

最后只有在get方法中才可以抛出异常,所以,使用submit时的注意了,执行时并没有抛出异常中断父线程的执行,而你还需要get一下才行,否则这问题很难找。

public V get() throws InterruptedException, ExecutionException {
        int s = state;
        if (s <= COMPLETING)
            s = awaitDone(false, 0L);
        return report(s);
    }

    public V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException {
        if (unit == null)
            throw new NullPointerException();
        int s = state;
        if (s <= COMPLETING &&
            (s = awaitDone(true, unit.toNanos(timeout))) <= COMPLETING)
            throw new TimeoutException();
        return report(s);
    }

结论请自己脑补,区别都列出来了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值