Java实现多线程的方法

java实现多线程的方式有三种:

1、继承Thread类,重写该类的run方法(Thread类实现了Runnable接口)

public class TestThread  extends Thread{

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		TestThread thread = new TestThread();
		thread.start();
	}
	
	public void run(){
		System.out.print("Thread is running");
	}

}

2、实现Runnable接口,实现接口中的run方法

public class TestThread  implements Runnable{

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Thread thread = new Thread(new TestThread());
		thread.start();
	}
	
	public void run(){
		System.out.print("Thread is running");
	}

}

3、实现Callable接口,实现call方法

public class TestThread  implements Callable{

	public static void main(String[] args) throws InterruptedException, ExecutionException {
		FutureTask task = new FutureTask(new TestThread());
		Thread thread = new Thread(task);
		thread.start();
		System.out.print(task.get());
	}
	
	public String call(){
		return "Thread is running";
	}

}

三者有何异同呢?我们来逐一比较:

1、首先我们都知道java类只能继承一个父类,但可以实现多个接口,因此对比继承Thread类,实现Runnable方法的同时还能继承我们需要的父类,显然这种方式更具有拓展性,且我们可以通过实现Runnable将线程任务的封装,交由多个线程一起执行

2、实现Callable方法相比于前两种方式,他需要实现call方法,且该方法有返回值,适合需要线程执行完之后返回结果的情况。例如我们有时候主线程想要做某一步操作,但是不必马上知道这个操作的结果,也不想在这个操作上进行等待,那可以new一个新线程,然后实现callable接口,让一个异步子线程去完成这个操作,然后主线程可以继续去做其他事情,等到需要用到这个操作返回结果的时候,就可以用fatureTaskd的get方法获取返回值。值得注意的是,如果异步子线程暂未执行完毕,get方法会一直阻塞直到拿到返回结果,当然,我们也可以选择使用get(long timeout,TimeUnit unit)来实现超时等待,若超过等待时间则不再阻塞,直接返回;future在NIO实现的netty中有广泛应用

3、实现callable接口的线程任务是可以通过futureTask的cancel方法进行取消的


那么,我们在什么时候需要用到多线程呢?

1、在硬件条件足够好的情况下,使用多线程增加任务处理速度;例如多核CPU系统,批量处理系统利用多线程加快任务处理速度;

2、在许多IO等待的场景下,若使用单线程则当IO阻塞时线程无法处理其他事物,导致卡死,或者线程出现异常中断后,导致功能不可用,此时也可以使用多线程

3、同步转异步场景下,我们需要使用一个子线程去进行某种操作,主线程继续往下执行或直接返回,减少响应等待的场景

是不是多线程一定比单线程好呢?

1、在单核CPU的物理机上,多线程上下文之间的频繁切换是很耗费cpu资源的,此时单线程是要比多线程快的;

2、线程的频繁创建、销毁也是消耗CPU性能和内存的,因此一般采用线程池管理





猜你喜欢

转载自blog.csdn.net/smartValentines/article/details/80572953