并发编程学习总结(一) :java 创建线程的三种方式的优缺点和实例

java 创建线程有三种方式:

(一)  实现Runnable接口  

       优点:(1) 创建线程的同时可以继承其他的类,从而可以扩展类的功能。

                  (2) 同一个实现Runnable接口的实例可以作为多个Thread的target,这样可以实现资源的共享。

       缺点:相对于继承Thread类,实现Runnable接口代码要繁琐一些

       代码实例如下:

public class ImplementsRunnable implements Runnable{
	
	@Override
	public void run() {
		System.out.println(Thread.currentThread().getName()+" ThreadId: "+ Thread.currentThread().getId());
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		// 输出主线程的相关信息
		System.out.println(Thread.currentThread().getName()+" ThreadId: "+ Thread.currentThread().getId());	
		
		// 创建thread1线程
		ImplementsRunnable runnableTarget = new ImplementsRunnable();
		Thread thread1 = new Thread(runnableTarget,"ThreadName1");
		thread1.start();
		
		// 以匿名内部类的形式创建target   创建thread2线程
		new Thread(new Runnable() {
			public void run() {
				System.out.println(Thread.currentThread().getName()+" ThreadId: "+ Thread.currentThread().getId());	
			}
		},"ThreadName2").start();
	}

}
输出结果:main ThreadId: 1
          ThreadName1 ThreadId: 9
          ThreadName2 ThreadId: 10


(二)  继承Thread 类,重载Thread类的run()方法。事实上Thread类也是实现了Runnable接口。

       优点:代码相对其他两种方式更简洁

       缺点:由于java的继承机制是单一继承,继承Thread类就不能继承其他的类。

       代码实例:

public class ExtendsThread extends Thread{
	
	public ExtendsThread(String threadName) {
		super(threadName);
	}

	public void run() {
		System.out.println("ThreadName: " + getName());
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		// 输出主线程的相关信息
		System.out.println(Thread.currentThread().getName()+" ThreadId: "+ Thread.currentThread().getId());	
		
		// 创建子线程
		ExtendsThread et = new ExtendsThread("childThread");
		et.start();

	}
}


(三)  实现Callable<V>接口 并实现接口的唯一方法call()

有些场景会希望得到线程的计算结果,这时可以实现Callable<V> 接口。Callable<V>接口和Runnable接口都是封装了一个异步任务,不同的是

Callable<V>接口具有返回值。同时Call<V>接口还是一个参数化的类型,这个参数就是线程的返回参数类型,比如线程若返回整型则Callable<Integer>

,若返回字符类型则为Callable<Object>。


通过实现Callable<V>接口创建线程,需要用到一个包装器FutureTask<V>,这个包装器同时实现了Runnable和Future<V>接口,它可以将Callable<V>

对象转换为Runnable和Future。

public interface Callable<V> {

	    V call() throws Exception;
   }
	
	public interface Future<V> {

	    boolean cancel(boolean mayInterruptIfRunning);

	    boolean isCancelled();

	    boolean isDone();

	    V get() throws InterruptedException, ExecutionException;

	    V get(long timeout, TimeUnit unit)
	        throws InterruptedException, ExecutionException, TimeoutException;
	}

	public interface RunnableFuture<V> extends Runnable, Future<V> {
	    /**
	     * Sets this Future to the result of its computation
	     * unless it has been cancelled.
	     */
	    void run();
	}
	
	
	public class FutureTask<V> implements RunnableFuture<V> {
	......
	}

代码实例:

public class ImplemetsCallable implements Callable<Integer>{
	
	// 实现call()方法
	public Integer call() {
		return  35;
	}

	public static void main(String [] args) throws 
	InterruptedException, ExecutionException, TimeoutException {
		
		ImplemetsCallable ic = new ImplemetsCallable();
		// 创建包装器 FutureTask 同时实现了Runnable和Future接口 可以将Callable 转换成Future和Runnable
		FutureTask<Integer> task = new FutureTask<Integer>(ic);
		Thread t = new Thread(task);
		t.start();
		//  调用FutureTask的get() 方法 获取线程的计算结果
		//  如果线程没有计算完结果 则get()方法会阻塞 直到线程计算完结果返回
		System.out.println(task.get());
		
		//  get(long timeout, TimeUnit unit)方法在指定时间内获取线程计算结果,超时则抛出 TimeoutException异常
		//  如果运行计算结果的线程被中断则get()和get(long timeout, TimeUnit unit)方法都将抛出InterruptedException异常
		System.out.println(task.get(10000, TimeUnit.MILLISECONDS));
	}

}

以下代码是通过使用线程池的方式创建线程:

public class TestCallable {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		System.out.println("程序开始执行");
		List<Future> list = new ArrayList<Future>();
		int taskSize = 5;  
		// 创建一个线程池  
		ExecutorService pool = Executors.newFixedThreadPool(taskSize); 
		
		for (int i = 0; i<taskSize; i++) {
			MyCallable mc = new MyCallable("i "+i);
			Future f = pool.submit(mc);
			list.add(f);
		}
		
		for (Future f : list) {
			try {
				System.out.println(f.get().toString());
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (ExecutionException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

}

class MyCallable implements Callable<Object> {
	
	private String name;
	
	public MyCallable(String name) {
		this.name = name;
	}
	
	public Object call() {
		System.out.println("任务开始执行>>>>");
		long beginTime = System.currentTimeMillis();
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		long endTime = System.currentTimeMillis();
		long durTime = endTime - beginTime;
		System.out.println("任务执行完毕>>>>");
		return name + "任务执行完毕>>>> 总耗时: "+ durTime;
	}
}







  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值