Java开启线程的四种方法
1,继承Thread类
继承Thread类,重写run方法(不推荐,因为java的单继承局限性)
1 public class ExtendThread extends Thread { 2 3 /* 4 * 创建步骤如下: 5 * 1,定义Thread类的子类,并重写该类的run()方法,该run()方法的方法体就代表了线程需要完成的任务。因此把run方法称为线程执行体。 6 * 2,创建Thread子类了的实例,即创建线程对象。本实例中是new一个ExtendThread,即可创建线程对象,也就是开启了一个线程 7 * 3,调用线程对象的start()方法来启动该线程。 8 * 9 * 调用示例: 10 * //循环10次即开启10个线程 11 * for (int i = 0; i < 10; i++) { 12 * ExtendThread extendThread = new ExtendThread(); 13 * extendThread.start(); 14 * } 15 * */ 16 17 /** 18 * 重写Thread类的run(),这个方法称为线程执行体 19 * */ 20 @Override 21 public void run() { 22 doSomething(); 23 } 24 25 /** 26 * 需要处理的任务 27 * */ 28 public void doSomething(){ 29 for (int i = 0; i < 10; i++) { 30 System.out.println(Thread.currentThread().getName() + "执行" + i); 31 } 32 } 33 }
2,实现Runnable接口
方式一:直接实现Runnable接口(避免单继承的局限性,方便共享资源,推荐使用)
1 public class RunnableImpl implements Runnable { 2 3 /* 4 * 创建步骤如下: 5 * 1,定义Runnable接口的实现类,并且实现run方法,这个方法同样是线程执行体 6 * 2,创建Runnable实现类的实例,并以此实例对象作为Thread的target来创建Thread类,这个新创建的Thread对象才是真正的线程对象,即开启了新的线程 7 * 3,调用线程对象的start()方法来开启该线程 8 * 9 * 调用示例: 10 * //开启10个线程 11 * for (int i = 0; i < 10; i++) { 12 * Thread thread = new Thread(new RunnableImpl()); 13 * thread.start(); 14 * } 15 * */ 16 17 /** 18 * 实现Runnable接口的run方法,这个方法称为线程执行体 19 * */ 20 @Override 21 public void run() { 22 doSomething(); 23 } 24 25 /** 26 * 需要处理的任务 27 * */ 28 private void doSomething(){ 29 for (int i = 0; i < 10; i++) { 30 System.out.println(Thread.currentThread().getName() + "执行" + i); 31 } 32 } 33 }
方式二:匿名内部类
1 public class Anonymous { 2 3 /* 4 * 创建步骤如下: 5 * 匿名内部类本质上也是一个类实现了Runnable接口,重写了run方法,只不过这个类没有名字,直接作为参数传入Thread类 6 * 7 * 调用示例: 8 * //开启10个线程 9 * for (int i = 0; i < 10; i++) { 10 * Anonymous anonymous =new Anonymous(); 11 * anonymous.myRun(); 12 * } 13 * 14 * */ 15 16 public void myRun(){ 17 new Thread(new Runnable() { 18 @Override 19 public void run() { 20 doSomething(); 21 } 22 }).start(); 23 } 24 25 /** 26 * 需要处理的任务 27 * */ 28 private void doSomething(){ 29 for (int i = 0; i < 10; i++) { 30 System.out.println(Thread.currentThread().getName() + "执行" + i); 31 } 32 } 33 }
3,实现Callable接口
1 public class CallableImpl implements Callable<String> { 2 3 /* 4 * 创建步骤如下: 5 * 1,定义实现Callable<V>接口的实现类,实现call方法,这个方法是线程执行体 6 * 2,创建Callable<V>实现类的实例,借助FutureTask得到线程执行的返回值 7 * 3,将FutureTask的实例,作为Thread的target来创建Thread类 8 * 4,调用start方法,开启线程 9 * 10 * 调用示例: 11 * Callable<String> tc = new CallableImpl(); 12 * FutureTask<String> task = new FutureTask<>(tc); 13 * new Thread(task).start(); 14 * try { 15 * System.out.println(task.get()); 16 * } catch (InterruptedException | ExecutionException e) { 17 * e.printStackTrace(); 18 * } 19 * 20 * 说明: 21 * 1.与使用Runnable相比, Callable功能更强大些 22 * 2.实现的call()方法相比run()方法,可以返回值 23 * 3.方法可以抛出异常 24 * 4.支持泛型的返回值 25 * 5.需要借助FutureTask类,比如获取返回结果 26 * Future接口可以对具体Runnable、Callable任务的执行结果进行取消、查询是否完成、获取结果等。 27 * FutureTask是Futrue接口的唯一的实现类 28 * FutureTask 同时实现了Runnable, Future接口。它既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值 29 * 30 * */ 31 32 private int ticket = 5; 33 34 @Override 35 public String call() throws Exception { 36 for (int i = 0; i < 10; i++) { 37 System.out.println(doSomething()); 38 } 39 40 return "出票任务完成"; 41 } 42 43 public String doSomething() { 44 String result = ""; 45 if (this.ticket > 0) { 46 result = "出票成功,ticket=" + this.ticket--; 47 } else { 48 result = "出票失败,ticket=" + this.ticket; 49 } 50 return result; 51 } 52 }
4,创建线程池
1 public class ThreadPool implements Runnable { 2 3 /* 4 * 创建步骤如下: 5 * 1,定义Runnable接口的实现类,或者定义(继承Runnable接口的类)的实现类,并且实现run方法,这个方法是线程执行体 6 * 2,创建一个自定义线程个数的线程池 7 * 3,实例化Runnable接口的实现类 8 * 4,将3步的实例,作为线程池实例的execute方法的command参数,开启线程 9 * 5,关闭线程池 10 * 11 * 调用示例: 12 * ExecutorService pool = Executors.newFixedThreadPool(2); 13 * ThreadPool threadPool = new ThreadPool("AA"); 14 * ThreadPool threadPoo2 = new ThreadPool("BB"); 15 * pool.execute(threadPool); 16 * pool.execute(threadPoo2); 17 * pool.shutdown(); 18 * 19 * 说明: 20 * 示例中创建的是2个线程的线程池 21 * execute方法是开启线程方法,实参要求是实现Runnable的类。所以,继承Thread类的子类也可以以线程池的方式开启线程 22 * 23 * */ 24 25 String name; 26 public ThreadPool(String name) { 27 this.name = name; 28 } 29 30 @Override 31 public void run() { 32 doSomething(); 33 } 34 35 /** 36 * 需要处理的任务 37 * */ 38 private void doSomething() { 39 for (int i = 0; i < 10; i++) { 40 System.out.println(Thread.currentThread().getName() + "执行" + i + ",name=" + this.name); 41 } 42 } 43 }