线程的创建方式
1、继承Thread类实现线程的创建方式(两种写法)
缺点:Java语言的设计当中只能实现单继承,如果继承了Thread类,就不能继承其他类了。
public class ThreadDemo4 {
static class MyThread extends Thread{
@Override
public void run() {
//线程执行任务
System.out.println("线程名称:" + Thread.currentThread().getName());
}
}
public static void main(String[] args) {
//创建了线程
Thread t1 = new MyThread();
//运行新线程
t1.start();
System.out.println("当前线程名称(主线程)"+Thread.currentThread().getName());
}
}
执行结果:
public class ThreadDemo5 {
public static void main(String[] args) {
Thread thread = new Thread(){
@Override
public void run() {
System.out.println("线程名称:"+Thread.currentThread().getName());
}
};
thread.start();
}
}
执行结果:
2、实现Runnable接口的方式创建线程(三种写法)
优点:Java不能实现多继承,但能实现多接口。
public class ThreadDemo6 {
static class MyRunnable implements Runnable{
@Override
public void run() {
System.out.println("线程名:"+Thread.currentThread().getName());
}
}
public static void main(String[] args) {
//新建Runnable类
MyRunnable runnable = new MyRunnable();
//新建Thread
Thread thread = new Thread(runnable);
//启动线程
thread.start();
}
}
执行结果:
public class ThreadDemo7 {
public static void main(String[] args) {
//使用匿名内部类实现线程
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("线程名称:"+ Thread.currentThread().getName());
}
});
thread.start();
}
}
执行结果:
public class ThreadDemo8 {
public static void main(String[] args) {
//lambda+匿名Runnable的实现方式
Thread thread = new Thread(()->{
System.out.println("线程名称:"+Thread.currentThread().getName());
});
thread.start();
}
}
执行结果:
3、实现Callable接口的方式创建线程(一种写法)
优点:可以得到线程结束之后的结果。
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
/**
* 创建并得到线程的执行结果
* 实现Callable接口+ Funture的方式
*/
public class ThreadDemo9 {
static class MyCallable implements Callable<Integer>{
@Override
public Integer call() throws Exception {
//随机生成一个随机数
int num =new Random().nextInt();
System.out.println("子线程:"+ Thread.currentThread().getName()+",随机数:" + num);
return num;
}
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
//创建一个Callable
MyCallable callable = new MyCallable();
//创建一个FutureTask对象来接收任务的返回值信息
FutureTask<Integer> futureTask = new FutureTask<>(callable);
//创建Thread
Thread thread = new Thread(futureTask);
//启动线程
thread.start();
int result = futureTask.get();
System.out.println(String.format("线程名:%s,数字:%d",Thread.currentThread().getName(),result));
}
}
执行结果:
线程休眠(三种方式)
import java.util.Date;
import java.util.concurrent.TimeUnit;
public class ThreadDemo10 {
public static void main(String[] args) throws InterruptedException {
System.out.println("开始时间"+new Date());
//休眠1秒钟
// Thread.sleep(1000);
//休眠的实现方式2
/*TimeUnit.SECONDS.sleep(1);//休眠一秒钟*/
//休眠实现方式3
Thread.sleep(TimeUnit.SECONDS.toMillis(1));
System.out.println("结束时间"+new Date());
}
}
线程分组
可以将一类线程归为一组,并且进行信息打印,查看一组线程的具体行为
import java.util.Random;
public class ThreadDemo11 {
public static void main(String[] args) {
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("开始跑了");
try {
int num = 1+new Random().nextInt(5);
Thread.sleep(num*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("我到终点了"+Thread.currentThread().getName());
}
};
//定义分组
ThreadGroup group = new ThreadGroup("百米赛一组");
//创建运动员
Thread t1 = new Thread(group,runnable,"张三");
Thread t2 = new Thread(group,runnable,"李四");
t1.start();
t2.start();
//打印线程分组的详情
group.list();
//等待所有选手到达终点
while (group.activeCount()!=0){
}
//宣布成绩
System.out.println("宣布成绩");
}
}
执行结果:
使用两个线程打印 AABBCCDD
public class ThreadTestDemo {
private static final String str = "ABCD";
public static void main(String[] args) {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i <str.length() ; i++) {
System.out.print(str.charAt(i));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
t1.start();
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i <str.length() ; i++) {
System.out.print(str.charAt(i));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
t2.start();
}
}
执行结果:
线程优先级
线程的优先级默认是5 [1,10]
优先值越大,权重越高
优先级总结:优先级越高,执行的优先级也越高,执行权也越大,但是CPU的调度是很复杂的,所以不会严格的按照优先级排序去执行,但总体情况是按优先级执行的。
线程分类
1、后台线程(守护线程)
2、用户线程(默认线程)
守护线程是用来服务用户线程的。
进程退出:没有用户线程执行,进程就会结束。
守护线程使用场景:Java垃圾回收器,健康检查
守护线程注意事项:
1、守护线程设置必须放在线程的启动之前(start()),如果在其之后,那程序就会报错,并且设置的值不能生效。
2、在守护线程里面创建的线程,默认是守护线程。
设置一个守护线程:
public class ThreadDemo14 {
public static void main(String[] args) {
Thread t1 = new Thread(()->{
for (int i = 0; i <10 ; i++) {
System.out.println("i:"+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
//设置守护线程
t1.setDaemon(true); //false
t1.start();
System.out.println("t1是否为守护线程"+ t1.isDaemon());
}
}
执行结果: