线程基础复习
程序:一段静态的代码
进程:正在执行的程序,是操作系统资源分配的最小单位
线程:进程可进一步细分为线程,是进程内部最小的执行单元,是操作系统进行任务调度的最小单元,属于进程
线程与进程的关系
-
一个进程可以包含多个线程,线程隶属于进程
-
一个进程中至少包含一个线程(主线程),在主线程中可以创建其他线程
-
一个进程内的所有线程共享该进程的内存资源
线程的创建
继承Thread类
类就不能继承其他类
public class MyThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println("MyThread:"+i);
}
}
}
public class Test {
/*
main启动java主线程
*/
public static void main(String[] args) {
//创建线程
MyThread myThread = new MyThread();
myThread.start();//启动线程
for (int i = 0; i < 1000; i++) {
System.out.println("main:"+i);
}
}
}
实现Runnable
类还可以继承其他类
public class ThreadeDemo implements Runnable{
/*
currentThread() 获得当前正在执行的线程对象
getName()获取线程名称
*/
@Override
public void run() {
/*for (int i = 0; i < 1000; i++) {
System.out.println(Thread.currentThread().getName()+":"+i);
}*/
System.out.println(Thread.currentThread().getName());
}
}
public class Test {
public static void main(String[] args) {
//创建线程执行任务
ThreadeDemo threadeDemo = new ThreadeDemo();
//Thread t = new Thread(threadeDemo);//这是创建线程
Thread t = new Thread(threadeDemo,"自定义线程");//这是创建线程,并为线程命名
//t.setName("");// 为线程命名的方法
t.start();//启动线程,在操作系统中注册,加入到就绪队列,并不是立即执行
t.setPriority(10);//设置优先级
Thread.currentThread().setPriority(1);
System.out.println(t.getPriority());//获得优先级
System.out.println(Thread.currentThread().getPriority());
System.out.println("main");
}
}
实现Callable接口
与使用Runnable相比,Callable功能更强大一些
相比run()方法,可以有返回值
方法可以抛出异常
支持泛型的返回值
需要借助FutureTask类,获取返回结果
public class SumThread implements Callable<Integer>{
@Override
public Integer call() throws Exception {
int num = 0;
for (int i = 0; i < 100; i++) {
num+=i;
}
return num;
}
}
public class Test {
public static void main(String[] args) throws ExecutionException, InterruptedException {
SumThread sumThread = new SumThread();
// 接收任务
FutureTask<Integer> futureTask = new FutureTask(sumThread);
// 创建线程
Thread t = new Thread(futureTask);
t.start();
Integer sum = futureTask.get();// 获得call方法返回值
System.out.println(sum);
}
}
线程的优先级
实际上,计算机上只有一个CPU,各个线程轮流获取到CPU的执行权,才能使用任务
优先级较高的线程有更多的机会获取到CPU,反之亦然
优先级用整数表示,取值范围在1~10,一般情况下线程默认优先级为5,但是可以通过setPriority和getPriority方法来设置或返回优先级;
调度策略:
-
时间片
-
抢占式:高优先级的线程抢占CPU
java的调度方法:
同优先级线程组成先进先出的队列,使用时间片的策略
高优先级,使用抢占式策略
线程状态
新建:当一个线程被声明并创建时,那么该线程就是新建状态
就绪:新建的线程被start()后,将进入等待线程的队列等待CPU的时间片
运行:当就绪的线程获取到CPU资源时,便进入到了运行状态
阻塞:在某种情况下,被认为挂起或者执行输入输出操作时,让CPU临时终止自己的执行,进入阻塞状态
死亡:线程完成了它的全部工作或者线程提前被强制终止或者出现了异常
线程的分类
java中的线程分为两类:用户线程和守护线程
通俗来讲,任何一个守护线程都是非守护线程的保姆,只要当前JVM中还存在任何一个非守护线程没有结束,那么守护线程就会一直工作,当最后一个非守护线程结束时,守护线程也会随之结束
ThreadDemo1 t1 = new ThreadDemo1();
t1.setDaemon(true);//设置线程为守护线程,必须在启动前设置,其他的用户线程结束,守护线程自动结束
t1.start();
注意:设置守护线程一定要在启动线程之前,否则会抛出一个
IllegalThreadStateException异常