多线程
进程:正在运行的程序,是系统进行资源分配和调用对的独立单位,每一个进程都有它的内存空间和系统资源。可以理解为,一个正在运行的程序。
线程:是进程中的单个顺序控制流,是一条执行路径,一个进程如果只有一条执行路径,则称为单线程程序;一个进程如果有多条执行路径,则称为多线程程序。
如何创建一个线程对象?
- 1、自定义线程类继承
Thread类,重写run方法 - 2、自定义线程类实现
Runable接口,实现run方法
如何启动一个线程?
调用start()方法启动
Thread无参构造方法
thread() 分配一个新的 Thread对象
class MyThread1 extends Thread{
MyThread1() {
}
MyThread1(String name){
super(name);
}
@Override
public void run() {
//将来线程启动后需要执行的逻辑
super.run();
}
}
注意:
- 1、启动一个线程的时候,若直接调用
run方法,仅仅是普通的对象调用方法,按照自上而下的顺序执行,底层不会额外的创建一个线程再执行 - 2、从执行结果上来看,java线程之间是抢占式执行的,谁先抢到cpu执行权谁就先执行
- 3、每次运行的结果顺序不可预测,是完全随机的
- 4、每个线程都有优先权,具有较高优先级的线程优先于优先级别低的线程执行
Thread类中的成员方法:
- 1、
public final String getName()获取线程对象的名字 - 2、设置线程对象名字的方式:
- a.通过父类的有参构造方法,在创建线程对象的时候设置名字
- b.线程对象调用
setName(String name)方法,给线程对象设置名字
- 3、获取进程的等级
getPriority()默认优先级是5 - 4、设置进程优先级,
setPriority(int i),在启动之前设置 [1,10]
注意不是优先级高的一定先执行,只是可能性变高了。
public class ThreadDemo1 {
public static void main(String[] args) {
//创建一个自己的线程对象
MyThread1 m1 = new MyThread1();
m1.setName("🐱");
// MyThread1 m1 = new MyThread1("🐱");
m1.setPriority(10);
System.out.println("m1:"+m1.getPriority());
}
}

接下来让我们来尝试启动多线程,在run()方法中定义线程启动后的逻辑
@Override
public void run() {
for (int i = 1; i <= 10;i++){
System.out.println(this.getName() + " - Hello world " + i);
}
}
启动多个线程,
public class TreadDemo2 {
public static void main(String[] args) {
MyThread2 m1 = new MyThread2();
m1.setName("🐱");
m1.setPriority(10);
System.out.println(m1.getName()+"的优先级为:"+ m1.getPriority());
MyThread2 m2 = new MyThread2();
m2.setName("🐜");
m2.setPriority(1);
System.out.println(m2.getName()+"的优先级为:"+m2.getPriority());
System.out.println("=======================");
m1.start(); //m1.run();
m2.start(); //m2.run();
}
}

了解了线程的调度后,接下来我们可以以下使用方法进行线程控制。
1、休眠线程
public static void sleep(long millis)
当线程处于休眠状态的时候,该线程就没有cpu执行权了,若这时还有其他的线程,会被抢走cpu执行权。
以下是示例:
class SleepThread extends Thread{
@Override
public void run() {
System.out.println(getName()+"睡着了。。。。");
try {
//这里使用try...catch..是因为sleep方法本身就抛出了一个异常,编译时期异常
Thread.sleep(1000);
//在哪个方法中调用,就是调用该方法的线程对象进行休眠
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(getName()+"睡醒了。。。。");
}
}
public class ThreadSleepDemo1 {
public static void main(String[] args) {
SleepThread s1 = new SleepThread();
s1.setName("🐱");
s1.start();
}
}

2、线程加入
public final void join()
当线程调用join()方法后,如果存在其他线程,则在该线程执行结束后,其他线程之间会进行抢占式执行。
class JoinThread extends Thread{
@Override
public void run() {
for (int i = 1; i <= 10; i++){
System.out.println(getName()+" - "+i);
}
}
}
public class ThreadJoinDemo1 {
public static void main(String[] args) {
JoinThread j1 = new JoinThread();
JoinThread j2 = new JoinThread();
JoinThread j3 = new JoinThread();
j1.setName("🐱");
j2.setName("🐕");
j3.setName("🐖");
j1.start();
try {
j1.join();// 其他线程等待该线程执行结束,其他线程之间会进行抢占式执行
} catch (InterruptedException e) {
e.printStackTrace();
}
j2.start();
j3.start();
}
}

3、线程礼让
public static void yield()
yield()只是为了运行结果看起来均匀一些
class YieldThread extends Thread{
@Override
public void run() {
for(int i = 1; i <= 10 ;i++){
System.out.println(getName()+" - "+i);
}
}
}
public class ThreadYieldDemo1 {
public static void main(String[] args) {
YieldThread y1 = new YieldThread();
YieldThread y2 = new YieldThread();
y1.setName("🐱");
y2.setName("🐕");
y1.start();
y2.start();
}
}

4、后台线程
public final void setDaemon(boolean on)
用户线程:没有调用Daemon方法的线程
守护线程:调用了Daemon方法的线程
在启动之前,设置一下,若一个进程中没有用户线程,守护线程也没有存在的必要。
class DaemonThread extends Thread{
@Override
public void run() {
for (int i = 1; i <= 200; i++){
System.out.println(getName()+" - "+i);
}
}
}
public class ThreadBaemonDemo1 {
public static void main(String[] args) {
DaemonThread d1 = new DaemonThread();
DaemonThread d2 = new DaemonThread();
DaemonThread d3 = new DaemonThread();
d1.setName("刘备");
d2.setName("关羽");
d3.setName("张飞");
d2.setDaemon(true);
d3.setDaemon(true);
d1.start();
d2.start();
d3.start();
}
}

这个例子的大概意思是,张飞、关羽线程在守护刘备线程,在刘备线程执行完后,张飞、关羽线程无论有没有执行完毕都会停止执行,而结果中之所以还有一段结果,是因为在计算机的一个小的时间片中,停止的信号还未传达到,所以还会执行几条。
5、中断线程
public final void stop():使用stop()方法,线程会直接结束,此方法已被弃用
public void interrupt():使用interrupt()方法,当线程睡眠时,会打断睡眠,提示异常,并执行完后续的语句
class StopThread extends Thread{
@Override
public void run() {
System.out.println(getName()+"睡着了。。。。");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(getName()+"睡醒了。。。。");
}
}
public class ThreadStopDemo1 {
public static void main(String[] args) {
StopThread s1 = new StopThread();
s1.setName("🐱");
s1.start();
try {
Thread.sleep(2000);
// s1.stop();//已经被弃用了
s1.interrupt();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}


浙公网安备 33010602011771号