回顾:
计算机:
——硬件:
——软件(os操作系统)内核系统【内核态】,用户部分【用户态】
进程:系统分配资源的最小单位
单进程程序–>多进程程序(缺点:不能互相共享资源)
线程:系统调度的最小单位。轻量级“进程”
优点:创建的时候占有更少的资源,并且多个线程间可以共享资源
线程共享的资源:
1,打开的文件
2,共享内存(new Object)
线程和进程之间的区别:
1.进程是系统分配资源的最小单位,线程是系统调度的最小单位
2.一个进程中至少包含一个线程
3.线程必须要依附于进程,线程是进程实质工作的一个最小单位
线程的创建方式:
1.继承Thread类是实现线程的创建线程(2种)
2.实现Runnable接口的方式(3种)
3.实现Callable接口的方式(可以得到线程执行之后的结果)
创建线程:继承Thread类
创建线程第一类,第一种方式:
static class MyThread extends Thread {
@Override
public void run() {
// 线程执行任务
System.out.println("线程名称:" +
Thread.currentThread().getName());
}
}
public static void main(String[] args) {
// 创建了线程
Thread t1 = new MyThread();
// 运行新线程
t1.start();
System.out.println("当前线程的名称(主线程):" +
Thread.currentThread().getName());
}
创建线程第一类,第二种方式:
public static void main(String[] args) {
Thread thread = new Thread() {
@Override
public void run() {
System.out.println("线程名:" +
Thread.currentThread().getName());
}
};
thread.start();
}
缺点:继承Thread类的方式的缺点,Java语言的设计只能实现单继承,如果继承了Thread类,也就不能继承其他类。
创建线程:实现Runnable接口的方式
第二类:实现Runnable接口的方式 Java不能多继承,但可以实现多个接口
创建线程第二类,第一种方式:
static class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("线程名:" +
Thread.currentThread().getName());
}
}
public static void main(String[] args) {
// 1.新建 Runnable 类
MyRunnable runnable = new MyRunnable();
// 2.新建 Thread
Thread thread = new Thread(runnable);
// 3.启动线程
thread.start();
}
创建线程第一类,第二种方式:
public static void main(String[] args) {
// 匿名内部类的方式实现线程
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("线程名:" +
Thread.currentThread().getName());
}
});
thread.start();
}
创建线程第二类,第三种方式:
public static void main(String[] args) {
// lambda + 匿名 runnable 的实现方式
Thread thread = new Thread(() -> {
System.out.println("线程名:" +
Thread.currentThread().getName());
});
thread.start();
}
创建线程:实现Callable接口的方式
package thread.thread_0425;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
/**
* 创建并得到线程的执行结果
* 实现 Callable 接口 + Future 的方式
*/
public class ThreadDemo9 {
// 创建了线程的任务和返回方法
static class MyCallable implements Callable<Integer> {
@Override
public Integer call() throws Exception {
// 生成一个随机数
int num = new Random().nextInt(10);
System.out.println("子线程:" +
Thread.currentThread().getName() +
",随机数:" + num);
return num;
}
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 1.创建一个 Callable
MyCallable myCallable = new MyCallable();
// 2.创建一个 FutrueTask 对象来接收返回值
FutureTask<Integer> futureTask =
new FutureTask<>(myCallable);
// 3.创建 Thread
Thread thread = new Thread(futureTask);
// 启动线程
thread.start();
// 得到线程执行结果
int result = futureTask.get();
System.out.println(String.format("线程名:%s,数字:%d",
Thread.currentThread().getName(), result));
}
}
线程休眠
休眠一秒:
Thread.sleep(1000);//方法一休眠一秒
TimeUnit.SECONDS.sleep(1);//方法二休眠一秒
//休眠实现方式3
Thread.sleep(TimeUnit.SECONDS.toMillis(1));
使用两个线程打印“AABBCCDD”
public static void main(String[] args) throws InterruptedException {
Runnable runnable=new Runnable() {
@Override
public void run() {
String str="ABCD";
for(char item:str.toCharArray()){
System.out.print(item);
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
Thread t1=new Thread(runnable);
Thread t2=new Thread(runnable);
t1.start();
t2.start();
}
ThreadGroup:线程分组
可以将一类线程分为一组,并且进行信息的打印,查看一组线程的具体行为。
线程优先级:新创建的线程默认优先级为5
优先级的取值是1~10,值越大(执行)权重越高
优先级总结:
优先级越高,执行的优先级也越高,执行权越大,但是CPU的调度是很复杂的,所以不会严格的按照优先级的排序去执行,但总体来看还是优先级越高执行的权重也越高。
线程的分类:
1.后台线程(守护线程)
2.用户线程【默认线程】
守护线程是用来服务用户线程的,用户线程就是上帝,守护线程就是服务员
进程退出:没有用户线程运行,进程就会结束
守护线程使用场景:Java垃圾回收器。健康检查
守护线程需要注意的事项:
1.守护线程设置必须在调用start之前();
如果设置守护线程在开始线程之后,那么程序就会报错,并且设置的守护线程值不能生效。
2在守护线程里面创建的线程,默认情况下全部都是守护线程