Java学习-09-韩顺平老师
Java-线程入门01
线程相关概念及基本使用
线程的相关概念:
- 进程
1.进程是指运行中的程序,比如我们使用qq,就会启动一个进程,操作系统就
会为改进程分配内存空间,当我们使用迅雷的,又启动了一个进程,操作系统
将为迅雷分配空间。
2.进程是程序的执行过程,或是正在运行的一个程序。是一个动态过程:有它自身
的残生、存在和消亡的过程。
- 线程
1.线程是进程创建的,是进程的一个实体。
2.一个进程可以右多个进程。
3.线程也可以载创建线程。
举例:当我们使用迅雷下载一个文件的时候,进程就会创建一个线程来下载,
如果又有一个文件要用迅雷下载,那么迅雷就会在创建一个线程下载。
4.单线程:同一个时刻,只允许执行一个线程。
5.多线程:同一个时刻,可以执行多个线程,比如qq可以同时打开多个聊天窗口.
6.并发:同一时刻,多个任务交给一个CPU来交替执行,造成一种"貌似同时"的错觉,
简单来说,单核Cpu实现多任务就是并发。
7.并行:同一时刻,多个任务由多个Cpu来执行,称为并行。
线程的基本使用
- 创建线程的两种基本方式
1.继承Thread类,重写run方法
public class ThreadWays {
public static void main(String[] args) {
Thread01 thread01 = new Thread01();
Thread01 thread02 = new Thread01();
thread01.start();
thread02.start();
}
}
class Thread01 extends Thread{
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程" +Thread.currentThread() + "正在打印i = " + i);
if (i == 8){
break;
}
}
}
}
2.实现Runnable接口,并重写run方法
public class ThreadWays {
public static void main(String[] args) {
Thread01 thread01 = new Thread01();
Thread01 thread02 = new Thread01();
// 但是这里不能使用start来启动线程
// 通过给Thread对象,传入一个 线程在调用start方法
new Thread(thread01).start();
new Thread(thread02).start();
}
}
class Thread01 implements Runnable{
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程" +Thread.currentThread() + "正在打印i = " + i);
if (i == 8){
break;
}
}
}
}
关于为什么线程调用start方法,而不是调用run方法:
1.调用start方法实际上底层是调用了start0() private native void start0();
这个方法是原生方法,是由JVM机调用的,可以理解为,由JVM机来调用我们定义的
run方法。
2.如果直接调用run方法,将不是创建线程来执行,会等run函数执行完,在执行其他代码。
线程终止:
1.当线程完成任务后,会自动退出。
2.还可以通过变量来控制run方法退出的方式俩停止线程,即通知方式。
线程的常用方法:
1.setName:设置线程名称
2.getName:返回线程的名称。
3.start:使该线程开始执行,Java虚拟机底层调用该线程的start0()方法。
4.run:调用线程对象的run 方法。
5.setPriority:设置线程的优先级。
6.getPriority:获取线程的优先级。
7.sleep:在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)。
8.interrupt:中断线程,不是退出线程。
9.yield:线程礼让,让出cpu,让其他线程执行,让的时间不确定,所以礼让不一定成功,
当cpu空间充足的时候,一般都是礼让失败.
10.join:线程插队,插队的线程一旦插队成功,则肯定先执行完插入线程的任务,再回来
当前线程的任务。
演示代码:
public class ThreadMethod {
public static void main(String[] args) {
Thread02 thread02 = new Thread02();
thread02.setName("线程1");
// Thread.MIN_PRIORITY = 1
// Thread.NORM_PRIORITY = 5
// Thread.MAX_PRIORITY = 10
thread02.setPriority(Thread.MIN_PRIORITY);
thread02.start();
}
}
class Thread02 extends Thread{
@Override
public void run() {
while (true){
System.out.println(this.getName()); // 线程1
System.out.println(this.getPriority()); // 1
try {
Thread.sleep(1000); // 休眠一秒钟
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
this.interrupt();// 中断当前线程,会进入下一个循环
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
join插队演示
public class YieldAndJoin {
public static void main(String[] args) {
Brother brother = new Brother();
Thread thread = new Thread(brother);
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread() + "正在运行" + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(i == 5){ // 当i=5的时候,让brother线程插队
try {
thread.start(); // 启动线程
thread.join(); // 采用join插队,一定成功,要等Brother线程执行完,才会回到主线程
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
class Brother implements Runnable{
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread() + "正在运行" + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
方法使用细节:
1.start底层会创建新的线程,调用run,run就是一个简单的方法调用,不会启动新的线程。
2.interupt 终端线程,但并没有真正的结束线程,所以一般用于中断正在休眠的线程。
3.sleep线程的静态方法,使当前线程休眠。
用户线程和线程守护
1.用户线程,也叫工作线程,当线程任务执行完或通知方式结束。
2.守护线程:一般为工作线程服务的,当所有用于线程结束,守护线程自动结束。
3.常见的守护线程:垃圾回收机制。
public class Daemon_ {
public static void main(String[] args) {
DaemonThread daemonThread = new DaemonThread();
daemonThread.setDaemon(true); // 将daemonThread设置为守护线程
daemonThread.start();
for (int i = 0; i < 10; i++) {
System.out.println("主线程正在运行");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("主线程退出啦"); // 当输出主线程退出啦,守护线程就会立马退出。
}
}
class DaemonThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println("守护线程正在运行!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}