Java多线程(1):3种常用的实现多线程类的方法
(1) 继承java.lang.Thread类(Thread也实现了Runnable接口)
继承Thread类的方法是比较常用的一种,如果说你只是想起一条线程。没有什么其它特殊的要求,那么可以使用Thread。一般推荐Runable。Thread类实际上也是实现了Runnable接口的类。
1 class ThreadDemo extends Thread { 2 3 private int i = 1; 4 5 ThreadDemo(String name) { 6 this.setName(name); 7 System.out.println("Creating " + name); 8 } 9 10 @Override 11 public void run() { 12 System.out.println("Running " + this.getName()); 13 try { 14 for (; i <= 5; i++) { 15 System.out.println("Thread: " + this.getName() + " [" + i + "]"); 16 // Thread.sleep()方法调用目的是不让当前线程独自霸占该进程所获取的CPU资源,以留出一定时间给其他线程执行的机会。 17 Thread.sleep((int) (Math.random() * 100)); 18 } 19 } catch (InterruptedException e) { 20 System.out.println("Thread " + this.getName() + " interrupted."); 21 } 22 System.out.println("Thread " + this.getName() + " exiting."); 23 } 24 25 @Override 26 public void start() { 27 System.out.println("Starting " + this.getName()); 28 super.start(); 29 } 30 } 31 32 // 程序启动运行main时候,java虚拟机启动一个进程,主线程main在main()调用时候被创建。 33 // 随着调用ThreadDemo的两个对象的start方法,另外两个线程也启动了,这样,整个应用就在多线程下运行。 34 public class TestThread { 35 public static void main(String args[]) { 36 ThreadDemo t1 = new ThreadDemo("Thread-1"); 37 // start()方法的调用后并不是立即执行多线程代码,而是使得该线程变为可运行态(Runnable),什么时候运行是由操作系统决定的。 38 t1.start(); 39 ThreadDemo t2 = new ThreadDemo("Thread-2"); 40 t2.start(); 41 } 42 }
(2) 直接实现java.lang.Runnable接口
通过实现Runnable接口,使得该类有了多线程类的特征。run()方法是多线程程序的一个约定。所有的多线程代码都在run方法里面。
在启动的多线程的时候,需要先通过Thread类的构造方法Thread(Runnable target) 构造出对象,然后调用Thread对象的start()方法来运行多线程代码。
如果一个类继承Thread,则不适合资源共享。但是如果实现了Runable接口的话,则很容易的实现资源共享。
1 class RunnableDemo implements Runnable { 2 3 private int i = 1; 4 5 RunnableDemo() { 6 System.out.println("Creating" + Thread.currentThread().getName()); 7 } 8 9 @Override 10 public void run() { 11 System.out.println("Running " + Thread.currentThread().getName()); 12 try { 13 for (; i <= 5; i++) { 14 System.out.println("Thread: " + Thread.currentThread().getName() + " [" + i + "]"); 15 Thread.sleep((int) (Math.random() * 100)); 16 } 17 } catch (InterruptedException e) { 18 System.out.println("Thread " + Thread.currentThread().getName() + " interrupted."); 19 } 20 System.out.println("Thread " + Thread.currentThread().getName() + " exiting."); 21 } 22 } 23 24 public class TestRunnable { 25 26 public static void main(String args[]) { 27 Runnable r1 = new RunnableDemo(); 28 Thread t1 = new Thread(r1); 29 t1.setName("Thread-1"); 30 t1.start(); 31 32 Runnable r2 = new RunnableDemo(); 33 Thread t2 = new Thread(r2); 34 t2.setName("Thread-2"); 35 t2.start(); 36 } 37 }
package com.mycloud.demo.thread; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; class CallableDemo implements Callable<String> { private int i = 1; CallableDemo() { System.out.println("Creating " + Thread.currentThread().getName()); } @Override public String call() { System.out.println("Running " + Thread.currentThread().getName()); try { for (; i <= 5; i++) { System.out.println("Thread: " + Thread.currentThread().getName() + " [" + i + "]"); Thread.sleep((int) (Math.random() * 100)); } } catch (InterruptedException e) { System.out.println("Thread " + Thread.currentThread().getName() + " interrupted."); return "failed"; } System.out.println("Thread " + Thread.currentThread().getName() + " exiting."); return "success"; } } public class TestCallable { public static void main(String args[]) { ExecutorService ex = Executors.newFixedThreadPool(5); List<Future<String>> futures = new ArrayList<>(); futures.add(ex.submit(new CallableDemo())); futures.add(ex.submit(new CallableDemo())); try { for (Future<String> future : futures) { System.out.println(future.get()); } } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } finally { ex.shutdown(); } } }