目录
一: 创建线程的第一种方式:继承Thread类(java.lang.Thread不需要导包)
一: 创建线程的第一种方式:继承Thread类(java.lang.Thread不需要导包)
1:步骤
1、自定义一个子类MyThread1继承Thread类
2、自定义类重写Thread类中的run()方法
3、创建子类对象(每new一次就相当于创建一个线程)
4、启动线程(不能多次启动,多次会报错java.lang.IllegalThreadStateException)
2:调用run()与调用start()的区别
run()的调用仅仅是封装了被线程执行的代码,但是直接调用的话是普通的方法调用
start()方法的调用,首先单独启动了一个线程,然后再由JVM去调用该线程的run()方法
3:获取和设置线程名字
通过构造方法给线程起名字:
Thread(String name) 分配一个新的 Thread对象。
通过方法给线程起名字:
void setName(String name) 将此线程的名称更改为等于参数 name 。
void getName(String name) 得到线程名字
如何获取main方法所在的线程名称呢?
public static Thread currentThread()
4:线程调度(两种模型)
分时调度模型 所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间片
抢占式调度模型 优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个,优先级高的线程获取的 CPU 时间片相对多一些。
Java使用的是抢占式调度模型。
5: 获取和设置线程的优先级
public final int getPriority()返回此线程的优先级。
设置线程的优先级
public final void setPriority(int newPriority)更改此线程的优先级
参数newPriority的范围为1-10之间
注意:1、线程的默认优先级为5
2、线程优先级的范围是1-10(超出范围报错java.lang.IllegalArgumentException)
3、线程优先级高仅仅表示的是获取CPU时间片的几率会高一些,但是不是绝对一定会获取
6:线程控制
(1:线程休眠(在run方法里休眠)(用Thread调用)
public static void sleep(long millis)(毫秒)
(2:线程加入
public final void join()(在main方法)(用对象调用)
其他线程等待这个线程死亡(执行完)
注意事项:在线程设置为加入线程之前,先将该线程变为就绪状态,也就是调用start()方法
(3:线程礼让(在run方法)(直接用)
public static void yield()
暂停当前正在执行的线程对象,并执行其他线程
它的作用是为了让多个线程之间更加和谐一点,并不并不能一定保证多个线程一人一次执行
(4:后台线程(守护线程)(在main方法用对象调用)
public final void setDaemon(boolean on)
通过这个方法将该线程对象标记为守护线程或者非守护线程。
当运行的程序只有一个线程且是守护线程的时候,Java虚拟机退出
注意:将线程设置为守护线程这一步骤,必须在启动前设置。
(5:中断线程
public final void stop()(在main方法中用对象调用)
让正在运行的线程停止,run方法剩下的代码不会执 行,这个方法过时了,被弃用了,但是还能使用
public void interrupt()(在main方法中用对象调用)
中断正在运行的线程,被中断的线程将run方法执行完毕,并抛出异常 java.lang.InterruptedException: sleep interrupted
7:线程种类
Java中有两类线程:用户线程、守护线程
用户线程:我们在学习多线程之前所有程序代码,运行起来都是一个个的用户线程。
守护线程:所谓的守护线程,指的就是程序运行的时候在后台提供了一种通用服务的线程。比如说
垃圾回收线程,它就是一个称职的守护者,并且这种线程并不属于程序不可或缺的部分。所以
非守护线程结束的时候,程序也就终止了,同时会杀死进程种所有的守护线程。
反过来说,只要程序种存在非守护线程,程序就不会终止。
二:例子
1:例子所用的实现Thread类的自定义类
package day32;
public class MyThread extends Thread{//定义一个 MyThread类继承Thread
@Override
//重写run方法实现从1到10的输出并且输出线程名字
public void run() {
for(int i =0;i<=10;i++){
System.out.println(Thread.currentThread().getName()+"**"+i);
}
}
}
2:设置获取名字以及设置获取优先级
package day32;
public class Thread1 {
public static void main(String[] args) {
//定义两个线程
MyThread myThread = new MyThread();
MyThread myThread1 = new MyThread();
//设置和获取线程名线程名
System.out.println(myThread.getName());
System.out.println(myThread1.getName());
System.out.println("=============================");
myThread.setName("线程1");
myThread1.setName("线程2");
System.out.println(myThread.getName());
System.out.println(myThread1.getName());
System.out.println("=============================");
//设置和获取线程优先级
System.out.println(myThread.getPriority());
System.out.println(myThread1.getPriority());
System.out.println("=============================");
myThread.setPriority(5);
myThread1.setPriority(8);
System.out.println(myThread.getPriority());
System.out.println(myThread1.getPriority());
}
}
通过观察发现线程有默认的名字Thread-0和Thread-1有默认的优先级5
3:休眠和加入
package day32;
public class MyThread extends Thread{//定义一个 MyThread类继承Thread
@Override
//重写run方法实现从1到10的输出并且输出线程名字
public void run() {
//执行前休眠3秒钟
try {
Thread.sleep(3000);
for(int i =0;i<=10;i++){
System.out.println(Thread.currentThread().getName()+"**"+i);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
package day32;
public class Thread1 {
public static void main(String[] args) {
//定义两个线程
MyThread myThread = new MyThread();
MyThread myThread1 = new MyThread();
//设置线程名字
myThread.setName("线程1");
myThread1.setName("线程2");
//启动线程
myThread.start();
//将myThread加入
try {
myThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
myThread1.start();
}
}
4:礼让和后台线程
package day32;
public class MyThread extends Thread{//定义一个 MyThread类继承Thread
@Override
//重写run方法实现从1到100的输出并且输出线程名字
public void run() {
for(int i =0;i<=100;i++){
System.out.println(Thread.currentThread().getName()+"**"+i);
yield();//礼让
}
}
}
package day32;
public class Thread1 {
public static void main(String[] args) {
//定义两个线程
MyThread myThread = new MyThread();
MyThread myThread1 = new MyThread();
//设置线程名字
myThread.setName("线程1");
myThread1.setName("线程2");
//将myThread设置为后台线程
myThread.setDaemon(true);
//启动线程
myThread.start();
myThread1.start();
}
}
当线程2执行结束后线程1没结束也关了
5;中断线程
package day32;
public class MyThread extends Thread{//定义一个 MyThread类继承Thread
@Override
//重写run方法实现从1到10的输出并且输出线程名字
public void run() {
for(int i =0;i<=10;i++){
System.out.println(Thread.currentThread().getName()+"**"+i);
}
}
}
package day32;
public class Thread1 {
public static void main(String[] args) {
//定义两个线程
MyThread myThread = new MyThread();
MyThread myThread1 = new MyThread();
//设置线程名字
myThread.setName("线程1");
myThread1.setName("线程2");
//将myThread中断
myThread.stop();
//启动线程
myThread1.start();
myThread.start();
}
}
package day32;
public class Thread1 {
public static void main(String[] args) {
//定义两个线程
MyThread myThread = new MyThread();
MyThread myThread1 = new MyThread();
//设置线程名字
myThread.setName("线程1");
myThread1.setName("线程2");
//启动线程
myThread1.start();
myThread.start();
//将myThread中断
myThread.interrupt();
}
}