1、继承Thread
先上代码:
//实现多线程
/*
* Thread实现多线程
* 子线程任务调用的方法都是在子线程中执行
* 每个线程都有自己的栈空间,共用一份堆内存
*
* */
public class test1 {
public static void main(String[] args) {
MyThread m = new MyThread();
m.start();
for(int i=0;i<5;i++){
System.out.println("笑嘻嘻嘻"+i);
}
}
}
package com.xiancheng;
//继承Thread类的子类叫线程类
public class MyThread extends Thread {
@Override
public void run() {
//run方法就是线程要执行的任务方法
//这里是一条新的执行路径
//想要开启这条路径,不是调用run方法,而是通过thread对象的start()来启动任务
//下面这个for循环是在这个子线程的栈空间里面实现的,执行完就弹栈
for(int i=0;i<5;i++){
System.out.println("哇哈哈哈"+i);
}
}
}
实现过程如下图所示:
继承Thread类,并重写run方法就是在创建一个新的执行路径,系统调用start()方法,启动一条线程,执行run方法
每个线程都拥有自己的栈空间,共用一份堆内存,子线程调用的方法,都是在创建子线程的栈中执行,也就是将run方法调入子线程的栈空间,调用完就弹出栈。
2、借用java的匿名类,直接调用start()方法
package com.xiancheng;
public class test2 {
public static void main(String[] args) {
new Thread(){
@Override
public void run() {
for(int i=0;i<5;i++){
System.out.println("笑嘻嘻嘻"+i);
}
}
}.start();
for(int i=0;i<5;i++){
System.out.println("哇哈哈哈"+i);
}
}
}
3、实现Runnable接口
public class MyRunnable implements Runnable{
@Override
public void run() {
for(int i=0;i<5;i++){
System.out.println("你好吗"+i);
}
}
}
//另一个java文件
public class test1 {
public static void main(String[] args) {
//实现Runnable
//创建一个任务对象
MyRunnable r = new MyRunnable();
//创建一个线程,并为其分配一个任务
Thread t = new Thread(r);
//执行这个线程
t.start();
for(int i=0;i<5;i++){
System.out.println("笑嘻嘻嘻"+i);
}
}
}
实现Runable 与 继承Thread相比有如下优势:
1、通过创建任务,然后给线程分配的方式来实现的多线程,更适合多个线程同时执行这个相同的任务
2、可以避免单继承带来的不便,因为java一个类只能继承一个类,用Runnable是实现的是接口
3、任务与线程的本身是分离的,提高了程序的健壮性
4、在线程池技术中,接收Runn类型的任务,不接收Thread类型的线程
4、带返回值的线程Callable
上面两个方法不影响主线程的运行,和主线程是并行执行的
第三个既可以和主线程一起走也可以让主线程等这个线程执行完再执行主线程,执行完这个线程还会有返回值
package com.xiancheng;
import javax.swing.*;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class testCallable {
public static void main(String[] args) throws ExecutionException, InterruptedException {
Callable<Integer> c = new MyCallable();
FutureTask<Integer> task = new FutureTask<>(c);
new Thread(task).start();
System.out.println(task.isDone()); //判断子线程是否以执行完毕,没有执行性完返回false
//System.out.println(task.cancel(true));
//取消(结束)子线程,参数为true表示确定取消,返回值为true表示终止线程成功,如果为false,一般是该线程已经执行完毕
Integer j = task.get(); //主线程会等待子线程执行完之后得到返回值才会往下走
System.out.println("返回值为"+j);
for(int i =0;i<10;i++){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(i);
}
}
static class MyCallable implements Callable<Integer>{
@Override
public Integer call() throws Exception {
for(int i =0;i<10;i++){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(i);
}
return 100;
}
}
}