线程的理解:
- 每个运行的程序都是一个进程,在一个进程中还可以有多个执行单元同时运行,这些运执行单元可以看作程序执行的一 条路径,被称为线程。
- 线程是CPU调度和执行的单位。
- 操作系统中的每一个进程中都至少存在一个线程。
- 当一个Java程序启动时就会产生一个进程, 该进程会默认创建一个线程, 在这个线程上会运行main ()方法中的代码。
线程创建:
1. Thread
Thread thread = new Thread(()->{
for (int i = 0; i < 100; i++) {System.out.print(" T" + i);
}
});
thread.start();
线程休眠使用sleep()方法
线程等待使用join()方法
线程中断设置标志位,当然Thread类内部包含了一个boolean的变量可以用来作为标记位,标记是否被中断Thread.interrupted()或者Thread.currentThread().isInterrupted()都可以
2. Runnable
class MyThread implements Runnable{public void run(){while (true){System.out.println("MyThread类的run方法");}}
}
public class Demo01 {public static void main(String[] args) {//创建一个实现了Runnable接口的对象MyThread myThread = new MyThread();//将该对象传给Thread类的构造函数Thread thread = new Thread(myThread);//thread对象调用start方法,在这里不会调用自身的run方法,它会调用myThread对象的run方法thread.start();while (true){System.out.println("Demo类的main方法");}}
}
创建一个线程是声明实现类Runnable接口。那个类然后重写run类的方法。然后可以分配类的实例,在创建的时候作为参数传递,并启动。
可以分为三步:
定义MyRunnable类实现Runnable接口
实现run()方法,编写线程执行体
创建线程对象,调用start()方法启动线程
3. 实现 Callable 接口
public class ThreadDemo {public static void main(String[] args) throws ExecutionException, InterruptedException {FutureTask futureTask = new FutureTask<>(new MyCallable());Thread t1 = new Thread(futureTask);t1.start();//如果 futureTask.get() 没得到结果,代码将一直等着System.out.println(futureTask.get());System.out.println("t1 线程执行完成");}static class MyCallable implements Callable {@Overridepublic Object call() {System.out.println("实现 Callable 接口创建线程");return "Callable 返回结果";}}
}
创建一个 MyCallable 内部类实现 Callable 接口,重写 call() 方法。
FutureTask 实现了 RunnableFuture,RunnableFuture 继承了 Runnable, Future。
意味着可通过 FutureTask 接收 Callable 中 call 方法的返回值。
并和 Runnable 一样,传入 Thread 中创建线程。
futureTask.get() 方法可以得到线程返回结果,但是该方法是阻塞的。
意味着如果 t1 线程一直在运算,main 线程需要一直等待 t1 的结束,拿到结果才能继续运行。
4. 使用线程池创建
public class ThreadDemo {public static void main(String[] args){//创建固定 5 个线程的线程池ExecutorService executorService = Executors.newFixedThreadPool(5);//用线程池执行 100 次任务for (int i = 0; i < 100; i++) {executorService.execute(new Runnable() {@Overridepublic void run() {System.out.println(Thread.currentThread().getName());}});}}
}
降低资源消耗。 通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
提高响应速度。 当任务到达时,任务可以不需要等到线程创建就能立即执行。
提高线程的可管理性。 如果无限制的创建线程,不仅会消耗系统资源,还会降低系统的稳定性,通过线程池可以进行统一的分配,调优和监控。
Java线程池类型有四种,分别为:newCachedThreadPool、newFixedThreadPool、newSingleThreadExecutor、newScheduleThreadPool。
1、newCachedThreadPool:创建一个可缓存线程池,如果线程池长度超过处理所需,可灵活回收空闲线程,若线程数不够,则新建线程。
2、newFixedThreadPool:创建一个固定大小的线程池。可控制并发的线程数量,如果工作线程数量达到线程池初始的最大数,则将提交的任务存入到池队列中。
3、newSingleThreadExecutor:创建一个单线程的线程池,即只创建唯一的工作者线程来执行任务,,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
4、newScheduleThreadPool:创建一个定长的线程池,支持定时及周期性任务执行。