实现Runnable与继承Thread 相比有如下优势:
1、通过创建任务,然后给线程分配的方式来实现的多线程,更适合多个线程同时执行相同任务的情况。
2、可以避免单继承所带来的局限性。
3、任务和线程本身分离的,提高了程序的健壮性
4、线程池技术,接收Runnable类型的任务,不接受Thread类型的线程
Thread类
构造方法:
Thread()
Thread(Runnable target)
Thread(Runnable target, String name)
方法:
getName()
getId() //返回此Thread的标识符
getPriority() //MAX_PRIORITY、MIN_PRIORITY、NORM_PRIORITY
setName(String name)
setPriority(int newPriority)
sleep(long millis) //导致当前正在执行的线程休眠(暂时停止执行)指定的毫秒数
sleep(long millis, int nanos) //导致当前正在执行的线程休眠(暂时停止执行)指定的毫秒数加上指定的纳秒数
start()
interrupt() //中断此线程
先定义一个继承Thread的子类
public class Mythread extends Thread{
//run方法就是线程要执行的任务方法
@Override
public void run() {
//这里的代码就是一条新的执行路径
//这里执行路径的触发方式,不是调用run方法,而是通过定义的Mythread对象的strat()来启动任务
for (int i =0;i<10;i++){
System.out.println("副线程"+i);
}
}
}
public class Demo {
public static void main(String[] args) {
Mythread thread = new Mythread();
thread.start();
for (int i =0;i<10;i++){
System.out.println("主线程"+i);
}
}
}
随机交替执行
简化方式
public class Demo {
public static void main(String[] args) {
//匿名内部类的方法调用start()方法
new Thread(){
@Override
public void run() {
for (int i =0;i<10;i++){
System.out.println("副线程"+i);
}
}
}.start();
for (int i =0;i<10;i++){
System.out.println("主线程"+i);
}
}
}
Runnabel接口
先定义一个实现Runnabel的子类
public class Myrunnabel implements Runnable{
@Override
public void run() {
//线程的任务
for (int i =0;i<10;i++){
System.out.println("副线程"+i);
}
}
}
public class Demo {
public static void main(String[] args) {
//1、创建一个任务对象
Myrunnabel r = new Myrunnabel();
//2、创建一个线程,为其分配一个任务
Thread t = new Thread(r);
//3/执行该线程
t.start();
for (int i =0;i<10;i++){
System.out.println("主线程"+i);
}
}
}
效果同上
获取线程名称
public class Demo2 {
public static void main(String[] args) {
//获取主线程的名称
System.out.println(Thread.currentThread().getName());
//获取副线程的名称
//Thread(Runnable target, String name)
//使用Thread匿名内部类调用start方法
new Thread(new Myrunnabel(),"111").start();
}
static class Myrunnabel implements Runnable{
@Override
public void run() {
//Thread.currentThread()获取当前线程
//getName()获取此线程的名称
System.out.println(Thread.currentThread().getName());
}
}
}
线程的中断
public class Demo2 {
public static void main(String[] args) {
//获取主线程的名称
//System.out.println(Thread.currentThread().getName());
//获取副线程的名称
//Thread(Runnable target, String name)
//使用Thread匿名内部类调用start方法
//new Thread(new Myrunnabel(),"111").start();
Thread t1 = new Thread(new Myrunnabel());
t1.start();
for(int i=0;i<5;i++){
System.out.println(Thread.currentThread().getName()+":"+i);
//Runnable父类没有该异常,Myrunnabel只能try—catch
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//中断t1副线程
t1.interrupt();
}
static class Myrunnabel implements Runnable{
@Override
public void run() {
//Thread.currentThread()获取当前线程
//getName()获取此线程的名称
//System.out.println(Thread.currentThread().getName());
for(int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+":"+i);
//Runnable父类没有该异常,Myrunnabel只能try—catch
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
//e.printStackTrace();
System.out.println("发现中断副线程标记,但是不死亡");
//使用return中断线程
//return;
}
}
}
}
}
加了return之后,中断线程
线程分为守护线程和用户线程
用户线程:当一个线程不包含任何存活的用户线程时,进程结束
守护线程:守护用户线程,当最后一个用户线程结束时,所有守护线程自动死亡
setDaemon(boolean on) //将此线程标记为守护线程(true)或用户线程
Thread t1 = new Thread(new Myrunnabel());
t1.setDaemon(true);
t1.start();
for(int i=0;i<5;i++){
System.out.println(Thread.currentThread().getName()+":"+i);
//Runnable父类没有该异常,Myrunnabel只能try—catch
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
执行完主线程后,守护线程t1死亡,但是关闭main函数有时间延迟,所有后面可能存在守护线程的一些操作
Callable 接口
第三种线程方式
public class Demo_Callable {
public static void main(String[] args) throws ExecutionException, InterruptedException {
Callable<Integer> c = new Mycallable();
FutureTask<Integer> task = new FutureTask<>(c);
new Thread(task).start();
//执行FutureTask的get()方法时,会阻塞主线程,等task任务执行完毕才执行主线程
Integer i = task.get();
System.out.println("返回的值是:"+i);
System.out.println("222");
}
static class Mycallable implements Callable<Integer>{
@Override
public Integer call() throws Exception {
for (int i=0;i<10;i++){
System.out.println(i);
Thread.sleep(1000);
}
return 100;
}
}
}