多线程简介
什么是线程?
线程是进程中的一个执行场景,一个进程可以启动多个线程
使用多线程可以提高CPU的使用率,不是提高执行速度。
线程和线程之间共享堆内存和方法区,栈内存是独立的,每个线程有自己独立的栈
进程包含多个线程。
多线程的缺点
- 设计复杂
多线程中共享堆内存和方法区,因此里面的一些数据是可以共享的,在设计时要确保数据的准确性 - 资源消耗增多
栈内存是不共享的,如果启用多个线程的话会占用更多的内存
多线程创建的三种方式之继承Thread类
package ThreadTest; /** * 多线程练习继承Thread */ public class ThreadTest01 { public static void main(String[] args) { new MyThread().start(); new Thread(){ @Override public void run() { for (int i = 0; i < 1000; i++) { System.out.println("线程1"); } } }.start(); } } class MyThread extends Thread{ @Override public void run() { for (int i = 0; i < 1000; i++) { System.out.println("线程0"); } } }
多线程创建的三种方式之实现Runnable接口
package ThreadTest; public class ThreadTest02 { public static void main(String[] args) { MyRunnable mr = new MyRunnable(); new Thread(mr).start(); new Thread(new Runnable(){ @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println("线程1"); } } }){ }.start(); } } class MyRunnable implements Runnable{ @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println("线程0"); } } }
多线程创建的三种方式之实现Callable接口
import java.util.ArrayList; 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; /** * 多线程实现的第三种方法,实现Callable接口 优点: 可以获取返回值 可以抛出异常 */ //1.定义一个类实现Callable<V>接口 class MyCallable implements Callable<Integer> { //睡眠时间 private long second; //计算阶乘 private int count; public MyCallable(int count, long second) { this.count = count; this.second = second; } // 2.重写call方法 @Override public Integer call() throws Exception { // 3.将要执行的代码写在call方法中 // 计算阶乘 //让当前线程睡眠,单位是毫秒 Thread.sleep(second); int sum = 1; if (count == 0) { sum = 0; } else { for (int i = 1; i <= count; i++) { sum *= i; } } // 打印线程名称 System.out.println(Thread.currentThread().getName() + "-----sum=" + sum); return sum; } public int getCount() { return count; } public void setCount(int count) { this.count = count; } } public class ThreadTest03 { public static void main(String[] args) throws InterruptedException, ExecutionException { //4.创建ExecutorService线程池 ExecutorService exec = Executors.newCachedThreadPool(); //5.创建存储Future对象的集合,用来存放ExecutorService的执行结果 ArrayList<Future<Integer>> results = new ArrayList<Future<Integer>>(); //6.开启2个线程,将返回的Future对象放入集合中 for (int i = 0; i < 2; i++) { if (i == 0) { //计算5的阶乘,睡眠10秒 results.add(exec.submit(new MyCallable(5, 10000))); } else { //计算3的阶乘,睡眠i秒 results.add(exec.submit(new MyCallable(3, i))); } } for (Future<Integer> fs : results) { //7.判断线程是否执行结束,如果执行结束就将结果打印 if (fs.isDone()) { System.out.println("计算结果:" + fs.get()); } else { System.out.println(fs.toString() + "该线程还没有计算完毕,请耐心等待"); } } //8.关闭线程池,不再接收新的线程,未执行完的线程不会被关闭 exec.shutdown(); System.out.println("main方法执行结束"); } }
匿名内部类的方式创建多线程
package ThreadTest; import java.util.concurrent.*; public class 匿名内部测试方法 { public static void main(String[] args) throws ExecutionException, InterruptedException { new Thread(){ @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println("Thread的线程"); } } }.start(); new Thread( new Runnable() { @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println("实现Runnable接口的线程"); } } } ){ }.start(); ExecutorService es = Executors.newCachedThreadPool(); //创建线程池 Future<Integer> submit = es.submit(new Callable<Integer>() { @Override public Integer call() throws Exception { return 1024; } }); System.out.println(submit.get()); } }
给线程命名和获取线程名
package ThreadTest; import java.util.concurrent.*; public class 匿名内部测试方法 { public static void main(String[] args) throws ExecutionException, InterruptedException { new Thread("Thread线程") { @Override public void run() { System.out.println(getName()); } }.start(); new Thread( new Runnable() { @Override public void run() { Thread.currentThread().setName("Runnable线程"); System.out.println(Thread.currentThread().getName()); } } ) { }.start(); ExecutorService es = Executors.newCachedThreadPool(); //创建线程池 Future<Integer> submit = es.submit(new Callable<Integer>() { @Override public Integer call() throws Exception { Thread.currentThread().setName("Callable线程"); System.out.println(Thread.currentThread().getName()); return 1024; } }); System.out.println(submit.get()); } }
线程睡眠
Thread中的sleep方法可以使当前线程睡眠,线程睡眠后,里面的任务不会执行,待睡眠时间过后会自动苏醒,从而继续执行任务。
Thread中有两个重载的sleep方法
sleep(long millis),指定睡眠毫秒数
sleep(long millis, int nanos),第一个参数是毫秒,第二个参数是纳秒。
package ThreadTest; /** * 使用Thread中的Sleep方法令线程睡眠 */ public class ThreadSleepTest01 { public static void main(String[] args) { // new Thread(){ // @Override // public void run() { // for (int i = 0; i < 10; i++) { // try { // Thread.sleep(1000); // } catch (InterruptedException e) { // e.printStackTrace(); // } // System.out.println("睡眠线程!"); // } // } // }.start(); // // new Thread(){ // @Override // public void run() { // for (int i = 0; i < 10; i++) { // try { // Thread.sleep(1000); // } catch (InterruptedException e) { // e.printStackTrace(); // } // System.out.println("1024"); // } // } // }.start(); new Thread() { @Override public void run() { for (int i = 10; i > 0; i--) { System.out.println(i); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); } }
唤醒正在睡眠的线程
package ThreadTest; /** * 使用Thread中的Sleep方法令线程睡眠 */ public class ThreadSleepTest01 { public static void main(String[] args) { Thread td = new Thread() { @Override public void run() { try { Thread.sleep(10000000); } catch (InterruptedException e) { e.printStackTrace(); } for (int i = 0; i < 10; i++) { System.out.println("sleep"); } } }; td.start(); td.interrupt(); } }
这里会打印出InterruptedException异常