java多线程
## 什么是线程 ### 进程 一个内存中运行的应用程序,每个进程有一个独立的内存空间,一个应用程序可以运行多个进程。
线程(thread)
线程是进程中的一个执行单元,负责当前进程中的执行,一个进程中至少要有一个线程。是操作系统能够进行运算调度的最小单位。是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。线程是独立调度和分派的基本单位。线程可以为操作系统内核调度的内核线程。
线程的调度
分时调度
所有线程轮流使用CPU控制权,平均分配每个线程占用CPU的时间。
抢占式调度
优先让优先级高的线程使用CPU,如果线程的优先级相同,那么会随机选择一个,Java使用的就是抢占式调度。
多线程的作用
可以更加充分地利用CPU的资源,使资源开销减小。
Java多线程创建
创建的方法
方法一:通过实现runnable接口
使用runnable接口是创建多线程最简单的方法
创建方法:
1.定义Runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体。
2.创建Runnable实现类的实例,并以此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象。
3.调用线程对象的start()方法来启动线程。
代码 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26class RunnableDemo implements Runnable{//1.创建一个runnable接口实现类
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println(Thread.currentThread().getName()+""+i);
}
}
}
public class ThreadDemo{
public static void main(String[] args) {
//创建定义的runnable接口实现类
RunnableDemo rd = new RunnableDemo();
//创建线程对象
Thread t = new Thread(rd, "小强");
//调用start方法启动线程
t.start();
for (int i = 0; i < 20; i++) {
System.out.println("旺柴"+i);
}
}
}
方法二: 通过集成Thread类本身
创建方法:
1.定义Thread类的子类,并重写该类的run()方法,该run()方法的方法体就代表了线程需要完成的任务,因此把 run()方法称为线程执行体。
2.创建Thread子类的实例,即创建线程对象
3.调用线程对象的start()方法来启动该线程
测试类代码 1
2
3
4
5
6
7
8
9
10
11
12public class Demo01 {
public static void main(String[] args) {
//创建自定义线程对象
MyThread mt = new MyThread("新的线程");
//开启新线程
mt.start();
//在主方法中执行for循环
for (int i = 0; i < 10; i++) {
System.out.println("main线程"+i);
}
}
}
自定义线程类 1
2
3
4
5
6
7public class MyThread extends Thread{
//定义指定线程名称的构造方法
public MyThread(String name){
//调用父类的string参数的构造方法,指定线程的名称
super(name);
}
}
方法三:Callable 和 Future 创建线程(不太使用)
创建方法
1.创建 Callable 接口的实现类,并实现 call() 方法,该 call() 方法将作为线程执行体,并且有返回值。
2.创建 Callable 实现类的实例,使用 FutureTask 类来包装 Callable 对象,该 FutureTask 对象封装了该 Callable 对象的 call() 方法的返回值。
3.使用 FutureTask 对象作为 Thread 对象的 target 创建并启动新线程。
4.调用 FutureTask 对象的 get() 方法来获得子线程执行结束后的返回值。
代码
1 | public class CallableThreadTest implements Callable<Integer> { |
实现Runnable接口相比继承Thread的优势
1.适合多个相同的程序代码的线程去共享同一个资源
2.可以避免java中的单继承的局限性。
3.增加程序的健壮性,实现解耦操作,代码可以被多个线程共享,代码和线程独立。
4.线程池只能放入实现Runable或Callable类线程,不能直接放入继承Thread的类。