标签:mit execution 利用 time exce 线程池 nts ace Fix
在并发编程中,创建线程是我们经常会做的事情,那么一般来说,创建线程有4种方式:
1、继承Thread类。
2、实现Runnable接口。
3、实现Callable接口,结合FutureTask来使用。
4、利用线程池的方式来实现。
public class ThreadTest1 extends Thread { @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("ThreadTest1 is running"); } public static void main(String[] args) throws InterruptedException { ThreadTest1 threadTest1=new ThreadTest1(); threadTest1.start(); System.out.println("第一次:"+System.currentTimeMillis()); Thread.sleep(1000); threadTest1.run(); System.out.println("第二次:"+System.currentTimeMillis()); } }
执行结果为: 第一次:1569155515336 ThreadTest1 is running ThreadTest1 is running 第二次:1569155517338
由上述例子可以看出,调用threadTest1.start()的时候先执行的输出时间然后执行的线程中的输出语句,而调用threadTest1.run()方法先执行的是ThreadTest1中的run()方法后执行主线程中的输出实际的语句,所以可以得出,直接调用run()方法不是启动线程的方式,而是直接调用线程中的run()方法和线程无关,启动线程的方式是调用Thread.start()方法。
public class ThreadTest2 implements Runnable { @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Thread is running"); } public static void main(String[] args) { ThreadTest2 threadTest2=new ThreadTest2(); Thread thread=new Thread(threadTest2); thread.start(); System.out.println(System.currentTimeMillis()); } }
实现接口Runnable来创建线程也是一种实现方式,与继承Thread类创建线程的不同在于,一个是继承、一个是实现接口,由于JAVA不允许多继承,所以在实际项目中实现Runnable接口来创建线程的方式还是用的比较多的。
public class ThreadTest3 implements Callable<Integer> { @Override public Integer call() throws Exception { int i = 0; for (; i < 100; i++) { System.out.println(Thread.currentThread().getName() + " " + i); } System.out.println(Thread.currentThread().getName() + " " + i); return i; } public static void main(String[] args) throws InterruptedException { ThreadTest3 threadTest3 = new ThreadTest3(); //很重要,无论多少个线程调用futureTask,futureTask只会执行一次 FutureTask<Integer> futureTask = new FutureTask<Integer>(threadTest3); Thread thread1 = new Thread(futureTask, "aa"); Thread thread2 = new Thread(futureTask, "bb"); Thread thread3 = new Thread(futureTask, "cc"); thread1.start(); Thread.sleep(3000); thread2.start(); Thread.sleep(3000); thread3.start(); try { System.out.println("最终结果为" + futureTask.get()); } catch (ExecutionException e) { e.printStackTrace(); } } }
实现Callable接口最重要的就是可以得到线程执行的返回值,但是实现Callable接口的类需要配合FutureTask来使用,同时我们注意到上面的例子很重要的一点,就是无论多少个线程来执行futuretask最终只会有一个线程执行,所以这种方法在并发变成中会很安全,不用担心多个线程调用了使得结果不正确。
使用线程池来创建线程
public class ThreadMain { public static void main(String[] args) throws InterruptedException, ExecutionException { ExecutorService executorService= Executors.newFixedThreadPool(3); Callable<Integer> callable=new ThreadTest3(); Future f=executorService.submit(callable); System.out.println("最终结果为" + f.get()); executorService.shutdown(); ExecutorService executorService2=Executors.newFixedThreadPool(3); Thread thread=new ThreadTest1(); executorService2.execute(thread); executorService2.shutdown(); } }
使用线程池来创建线程主要依靠的是Executors中的静态方法来创建线程池,实际上该种方法来创建线程本质还是上面3种方式,只不过在实际运用中使用多线程来执行任务用的比较多。
标签:mit execution 利用 time exce 线程池 nts ace Fix
原文地址:https://www.cnblogs.com/rhodesis/p/11569178.html