下面笔记来源尚硅谷,仅供学习。
基本流程
- 定义一个类,继承Thread
- 重写run方法,在run方法中设置线程任务(所谓的线程任务指的是此线程要干的具体的事儿,具体执行的代码)
- 创建自定义线程类的对象
- 调用Thread中的start方法,开启线程,jvm自动调用run方法
方法一:继承类
public class Test01 {
public static void main(String[] args) {
//创建线程对象
MyThread t1 = new MyThread();
//调用start方法,开启线程,jvm自动调用run方法
t1.start();
for (int i = 0; i < 10; i++) {
System.out.println("main线程..........执行了"+i);
}
}
}
public class MyThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("MyThread...执行了"+i);
}
}
}
Thread 类中的方法
void start() -> 开启线程,jvm自动调用run方法
void run() -> 设置线程任务,这个run方法是Thread重写的接口Runnable中的run方法
String getName() -> 获取线程名字
void setName(String name) -> 给线程设置名字
static Thread currentThread() -> 获取正在执行的线程对象(此方法在哪个线程中使用,获取的就是哪个线程对象)
static void sleep(long millis)->线程睡眠,超时后自动醒来继续执行,传递的是毫秒值
void setPriority(int newPriority) -> 设置线程优先级,优先级越高的线程,抢到CPU使用权的几率越大,但是不是每次都先抢到
int getPriority() -> 获取线程优先级 默认为5 最小1 最大10
void setDaemon(boolean on)
//设置为守护线程,当非守护线程执行完毕,守护线程就要结束
//但是守护线程也不是立马结束,会延迟一小段时间结束
static void yield() -> 礼让线程,让当前线程让出CPU使用权
void join() -> 插入线程或者叫做插队线程
public class MyThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 10; i++) {
//线程睡眠
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(Thread.currentThread().getName()+"...执行了"+i);
}
}
}
public class Test01 {
public static void main(String[] args) throws InterruptedException {
//创建线程对象
MyThread t1 = new MyThread();
//给线程设置名字
t1.setName("金莲");
//调用start方法,开启线程,jvm自动调用run方法
t1.start();
for (int i = 0; i < 10; i++) {
Thread.sleep(1000L);
System.out.println(Thread.currentThread().getName()+"线程..........执行了"+i);
}
}
}
问题:为啥在重写的run方法中有异常只能try,不能throws?
原因:继承的Thread中的run方法没有抛异常,所以在子类中重写完run方法之后就不能抛,只能try
线程优先级
public class MyThread1 extends Thread{
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+"执行了......"+i);
}
}
}
public class Test01 {
public static void main(String[] args) {
MyThread1 t1 = new MyThread1();
t1.setName("金莲");
MyThread1 t2 = new MyThread1();
t2.setName("阿庆");
/*
获取两个线程的优先级
MIN_PRIORITY = 1 最小优先级 1
NORM_PRIORITY = 5 默认优先级 5
MAX_PRIORITY = 10 最大优先级 10
*/
//System.out.println(t1.getPriority());
//System.out.println(t2.getPriority());
//设置优先级
t1.setPriority(1);
t2.setPriority(10);
t1.start();
t2.start();
}
}
守护线程
public class Test01 {
public static void main(String[] args) {
MyThread1 t1 = new MyThread1();
t1.setName("金莲");
MyThread2 t2 = new MyThread2();
t2.setName("阿庆");
//将t2设置成守护线程
t2.setDaemon(true);
t1.start();
t2.start();
}
}
public class MyThread1 extends Thread{
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+"执行了......"+i);
}
}
}
public class MyThread2 extends Thread{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName()+"执行了..."+i);
}
}
}
比如QQ聊天,聊天的同时可以传输文件,可以把传输文件的过程设置为守护线程
礼让线程
只是尽可能的礼让
public class Test01 {
public static void main(String[] args) {
MyThread1 t1 = new MyThread1();
t1.setName("金莲");
MyThread1 t2 = new MyThread1();
t2.setName("阿庆");
t1.start();
t2.start();
}
}
public class MyThread1 extends Thread{
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+"执行了......"+i);
Thread.yield();
}
}
}
插入线程
就是插队
public class MyThread1 extends Thread{
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+"执行了......"+i);
}
}
}
public class Test01 {
public static void main(String[] args) throws InterruptedException {
MyThread1 t1 = new MyThread1();
t1.setName("金莲");
t1.start();
/*
表示把t1插入到当前线程之前,t1要插到main线程之前,所以当前线程就是main线程
*/
t1.join();
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+"执行了......"+i);
}
}
}
方法二:实现接口
基本过程:
- 创建类,实现Runnable接口
- 重写run方法,设置线程任务
- 利用Thread类的构造方法:Thread(Runnable target),创建Thread对象(线程对象),将自定义的类当参数传递到Thread构造中 -> 这一步是让我们自己定义的类成为一个真正的线程类对象
- 调用Thread中的start方法,开启线程,jvm自动调用run方法
public class Test01 {
public static void main(String[] args) {
MyRunnable myRunnable = new MyRunnable();
/*
Thread(Runnable target)
*/
Thread t1 = new Thread(myRunnable);
//调用Thread中的start方法,开启线程
t1.start();
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+"...执行了"+i);
}
}
}
public class MyRunnable implements Runnable{
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+"...执行了"+i);
}
}
}
还可以使用匿名内部类创建多线程:
1.new 接口/抽象类(){
重写方法
}.重写的方法();
2.接口名/类名 对象名 = new 接口/抽象类(){
重写方法
}
对象名.重写的方法();
public class Test02 {
public static void main(String[] args) {
/*
Thread(Runnable r)
Thread(Runnable target, String name) :name指的是给线程设置名字
*/
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+"...执行了"+i);
}
}
},"阿庆").start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+"...执行了"+i);
}
}
},"金莲").start();
}
}
两种创建方式的区别:
- 继承Thread:继承只支持单继承,有继承的局限性
- 实现Runnable:没有继承的局限性, MyThread extends Fu implements Runnable