JAVA多线程实现-单线程化线程池newSingleThreadExecutor

    JAVA通过Executors提供了四种线程池,单线程化线程池(newSingleThreadExecutor)、可控最大并发数线程池(newFixedThreadPool)、可回收缓存线程池(newCachedThreadPool)、支持定时与周期性任务的线程池(newScheduledThreadPool)。本篇文章主要介绍newSingleThreadExecutor,其他三种线程池将在后续的文章中一一阐述。

单线程化线程池(newSingleThreadExecutor)的优点,串行执行所有任务。如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它。此线程池保证所有任务的执行顺序按照任务的提交顺序执行。(在后续阐述(newFixedThreadPool)时,我们会再做阐述)。


使用单线程化线程池(newSingleThreadExecutor)的一般方法下代码所示。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class ThreadPoolByNewSingleThreadExecutor {

	public static void main(String[] args) {
		/**
		 * 单线程化的线程池
		 */
		ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
		for (int i = 0; i < 10; i++) {
			final int index = i;
			singleThreadExecutor.execute(new Runnable() {
				@Override
				public void run() {
					Thread.currentThread().setName("Thread i = " + index);
					System.out.println(Thread.currentThread().getName() + " index = " + index);
					try {
						Thread.sleep(500);
					} catch (InterruptedException e) {
						System.out.println("ssss");
					}
				}
			});
		}
		singleThreadExecutor.shutdown();
		System.out.println("on the main thread...");
		
	}

}

后续的shutdown()方法用来关闭线程池,拒绝新任务。执行shutdown()方法后,线程池状态变为SHUTDOWN状态,此时,不能再往线程池中添加新任务,否则会抛出RejectedExecutionException异常。此时,线程池不会立刻退出,直到添加到线程池中的任务都已经处理完成,才会退出,即在终止前允许执行以前提交的任务。还有一个类似的方法shutdownNow(),执行shutdownNow()方法后,线程池状态会立刻变成STOP状态,并试图停止所有正在执行的线程,不再处理还在池队列中等待的任务,会返回那些未执行的任务。ShutdownNow()并不代表线程池就一定立即就能退出,它可能必须要等待所有正在执行的任务都执行完成了才能退出。

用ShutdownNow()关闭线程的代码示例

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class ThreadPoolByNewSingleThreadExecutor {

	public static void main(String[] args) {
		/**
		 * 单线程化的线程池
		 */
		ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
		for (int i = 0; i < 10; i++) {
			final int index = i;
			singleThreadExecutor.execute(new Runnable() {
				@Override
				public void run() {
					Thread.currentThread().setName("Thread i = " + index);
					System.out.println(Thread.currentThread().getName() + " index = " + index);
					try {
						Thread.sleep(500);
					} catch (InterruptedException e) {
						System.out.println("ssss");
					}
				}
			});
		}
		try {
			if (!singleThreadExecutor.awaitTermination(2*1000, TimeUnit.MILLISECONDS)) {
				singleThreadExecutor.shutdownNow();
			}
		} catch (InterruptedException e) {
			// awaitTermination方法被中断的时候也中止线程池中全部的线程的执行。
			 System.out.println("awaitTermination interrupted: " + e);
			singleThreadExecutor.shutdownNow();
		}
		System.out.println("on the main thread...");
		
	}

}



### 回答1: Java实现多线程的方式有以下几种:1.实现Runnable接口;2.继承Thread类;3.使用ExecutorService、Callable、Future等实现线程。实现Runnable接口和继承Thread类的区别在于,实现Runnable接口可以避免Java的单继承限制,在继承其他类的情况下可以同时实现多线程;而使用ExecutorService、Callable、Future等实现线程,可以更加方便地管理线程,比如可以指定线程的数量、线程的优先级等。 ### 回答2: 在Java中,有三种常见的方式来实现多线程:使用Thread类、实现Runnable接口和实现Callable接口。 1. 使用Thread类:通过继承Thread类,创建一个新的类,并重写其run方法来定义线程的执行逻辑。使用这种方式创建多线程,可以直接调用线程对象的start方法来启动线程。例如: ``` public class MyThread extends Thread { @Override public void run() { // 线程的执行逻辑 } public static void main(String[] args) { MyThread thread = new MyThread(); thread.start(); } } ``` 2. 实现Runnable接口:通过实现Runnable接口,创建一个新的类,并实现其run方法来定义线程的执行逻辑。然后使用该实现类创建一个线程对象,并将其作为参数传递给Thread类的构造方法。最后调用线程对象的start方法来启动线程。例如: ``` public class MyRunnable implements Runnable { @Override public void run() { // 线程的执行逻辑 } public static void main(String[] args) { MyRunnable runnable = new MyRunnable(); Thread thread = new Thread(runnable); thread.start(); } } ``` 3. 实现Callable接口:通过实现Callable接口,创建一个新的类,并实现其call方法来定义线程的执行逻辑。然后使用该实现类创建一个Callable对象,并将其作为参数传递给ExecutorService的submit方法。最后调用Future对象的get方法获取线程执行的结果。例如: ``` public class MyCallable implements Callable<String> { @Override public String call() throws Exception { // 线程的执行逻辑 return "Thread completed successfully"; } public static void main(String[] args) throws Exception { MyCallable callable = new MyCallable(); ExecutorService executor = Executors.newSingleThreadExecutor(); Future<String> future = executor.submit(callable); String result = future.get(); System.out.println(result); executor.shutdown(); } } ``` 这三种方式的区别在于实现方式不同。使用Thread类能直接继承该类并重写run方法,但无法继承其他的父类;而实现Runnable接口和实现Callable接口都可以继续继承其他父类。此外,通过实现Callable接口可以有返回值,并且可以抛出异常,在执行完任务后能获取任务的执行结果。 ### 回答3: 在Java中,实现多线程的方式有三种:继承Thread类、实现Runnable接口和使用Callable和Future接口。 1. 继承Thread类:创建一个类并继承Thread类,在该类中重写run方法来定义线程的任务。然后创建该类的实例,并调用start方法启动线程。这种方式简单易用,但因为Java只支持单继承,所以继承了Thread类之后不能再继承其他类。 2. 实现Runnable接口:创建一个类实现Runnable接口,并实现其中的run方法来定义线程的任务。然后创建Thread类的实例,将Runnable接口的实现类的实例作为参数传入Thread类的构造方法中,并调用start方法启动线程。这种方式灵活性较好,可以实现多重继承。 3. 使用Callable和Future接口:创建一个类实现Callable接口,并实现其中的call方法来定义线程的任务。Callable接口比Runnable接口更强大,它的call方法可以返回执行结果。然后创建ExecutorService类的实例,通过submit方法将Callable接口的实现类的实例提交给线程池执行,并返回一个Future对象,通过Future对象可以获取线程执行的返回结果。这种方式可以获取线程的执行结果,比较适合有返回结果的任务。 总结来说,继承Thread类的方式简单,但灵活性较差;实现Runnable接口的方式灵活性较好,可以实现多重继承;使用Callable和Future接口的方式可以获取线程的执行结果,适合有返回结果的任务。根据具体的需求和场景来选择适合的多线程实现方式。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值