Java-多线程的创建
1.多线程创建的两种方法
方法1 :继承于Thread 类
-
创建一个继承于Thread类的子类
-
重写Thread类的
run()
方法 ,将线程要执行的操作声明在run()方法中 -
通过子类的对象调用
start()
方法code 举例: 遍历100以内的所有偶数:
package com.lmw.thred;
public class ThreadTest {
public static void main(String[] args) {
// 主线程创建一个对象
MyThread t1 = new MyThread();
// 主线程对象启动子线程,执行子线程的start方法 通过start()方法执行run方法
// start 方法作用:启动当前线程、调用当前线程的run()方法
t1.start();
// 也可以通过匿名子类的方式实现
new Thread(){
@Override
public void run() {
for (int i = 0; i < 100; i++) {
if(i % 2 != 0) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
}.start();
}
System.out.println(Thread.currentThread().getName() + ":" + "我是主线程,我不等待子线程执行完成");
}
}
//继承Thread类
class MyThread extends Thread {
//重写run方法
@Override
public void run() {
for(int i = 0; i < 100; i++) {
if (i % 2 == 0) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
}
方法2:实现Runnable接口
- 创建一个类实现了Runnable接口
- 实现类去实现Runnable中的抽象方法:run()
- 创建类的对象
- 将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象
- 通过Thread类的对象调用start()方法,
//通过Thread类的对象调用start():启动线程/调用当前线程的run()方法(调用了Runnable类类型的target的run方法)
package com.lmw.thred;
public class ThreadTest1 {
public static void main(String[] args) {
MThread m1 = new MThread();
// 创建t1的子线程
Thread t1 = new Thread(m1);
t1.setName("线程1");
//通过Thread类的对象调用start():启动线程/调用当前线程的run()方法(调用了Runnable类类型的target的run方法)
t1.start();
//在启动一个线程
Thread t2 = new Thread(m1);
t2.setName("线程2");
t2.start();
}
}
class MThread implements Runnable{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
if(i % 2 == 0) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
}
方法1 和 方法2的区别
开发中优先选择实现Runnable接口的方式实现多线程:
- 实现方式没有类的单继承性的限制
- 实现的方式更适合用来处理多个线程共享数据的情况
// Thread类也实现了Runnable接口
public class Thread implements Runnable
2.Thread类中的常用方法
-
start()
启动当前线程,调用当前线程中的run()方法
-
run()
通常需要重写的Thread类中的此方法,将创建的线程要执行的操作声明在此方法中
-
currentThread()
静态方法,返回执行当前代码的线程对象
-
getName()
获取当前线程的名字
-
setName()
设置当前线程的名字
设置线程的名字是也可以使用Thread线程的构造方法实现
-
yield()
释放当前线程CPU的执行权,但是不一定下一刻就是其他线程在执行,有可能CPU又给这个线程分配了执行权
-
join()
在线程a中调用线程b中的join(),此时线程a就进入阻塞状态,直到线程b执行完成后,线程a才会继续执行
-
sleep(long millis)
让当前线程睡眠指定的毫秒数,在指定的毫秒时间内,当前线程是阻塞状态
-
isAlive()
判断当前线程是否还存活
package com.lmw.thred;
public class ThreadMethodTest {
public static void main(String[] args) {
Mothered t1 = new Mothered("线程1");
t1.start();
Thread.currentThread().setName("主线程");
for (int i= 0; i <100 ; i++) {
if(i % 2 == 0) {
System.out.println(Thread.currentThread().getName() + ":" +i);
}
if(i % 20 == 0) {
try {
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
System.out.println(t1.isAlive());;
}
}
class Mothered extends Thread {
/**
* @param name 线程名
*/
public Mothered(String name) {
super(name);
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
if(i % 2 == 0) {
// 阻塞 单位毫秒
try {
sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
}
3.线程的调度
- 同优先级线程组成先进先出队列(先到先服务),使用时间片策略
- 对高优先级,使用优先调度的抢占式策略