目录
Java中创建线程有哪些方式?
方式一:继承Thread,重写run
1、定义Thread类的子类MyThread,重写run()方法【线程执行体、就是线程要执行的任务】。
2、创建MyThread类的实例
3、调用子类实例的start()方法来启动线程
class MyThread extends Thread {
@Override
public void run() {
while(true) {
System.out.println("thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
public class Test1 {
public static void main(String[] args) {
MyThread myThread = new MyThread();
myThread.start();//执行这个的同时,也会继续向下执行
//并发
while(true) {
System.out.println("main");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
注:输出的thread和main大致上是交替输出,但说到底也不是严格的交替,因为无法确定哪个先执行,所以也会出现连续输出两个main或者thread,然后输出另一个
方式二:实现Runnable接口,重写run
1、定义Runnable接口的实现类,必须重写run()方法,这个run()方法和Thread中的run()方法一样,是线程的执行体
2、创建Runnable实现类的实例,并用这个实例作为Thread的target来创建Thread对象,这个Thread对象才是真正的线程对象
3、调用start()方法
class MyRunnable implements Runnable {
@Override
public void run() {
while(true) {
System.out.println("Thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
public class Test2 {
public static void main(String[] args) {
MyRunnable myRunnable1 = new MyRunnable();
Thread thread = new Thread(myRunnable1);
thread.start();
while(true) {
System.out.println("main");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
方式三:使用匿名内部类,实现创建Thread子类
类比于方式一
public class Test3 {
public static void main(String[] args) {
Thread thread = new Thread() {
@Override
public void run() {
while (true) {
System.out.println("Thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
};
thread.start();
while(true) {
System.out.println("main");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
方式四:使用匿名内部类,实现Runnable接口
类比于方式二
public class Test4 {
public static void main(String[] args) {
Thread thread = new Thread(new Runnable(){
@Override
public void run() {
while(true) {
System.out.println("Thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
});
thread.start();
while(true) {
System.out.println("main");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
方式五:lambda表达式——推荐使用
public class Test5 {
public static void main(String[] args) {
Thread thread = new Thread(()->{
while(true) {
System.out.println("Thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
thread.start();
while(true) {
System.out.println("main");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
方式六:Callable和Future接口创建并启动线程
步骤如下:
1、创建Callable接口实现类,并实现call()方法,该方法将作为线程执行体,且该方法有返回值,再创建Callable实现类的实例;
2、使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值;
3、使用FutureTask对象作为Thread对象的target创建并启动新线程;
4、调用FutureTask对象的get()方法来获得子线程执行结束后的返回值。
public class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println("实现Callable接口方式");
return "返回值"; // 返回值,类型和Callable泛型一致,这里用String举例
}
public static void main(String[] args) {
// 创建Callable实现类对象
MyCallable callable = new MyCallable();
// 将callable作为参数创建FutureTask对象
FutureTask<String> futureTask = new FutureTask<>(callable);
// 将futureTask作为参数创建线程
Thread thread = new Thread(futureTask);
thread.start(); // 启动线程
try {
// 获取线程执行后的返回值
String result = futureTask.get();
System.out.println(result);
} catch (Exception e) {
e.printStackTrace();
}
}
}
方式七:使用线程池
通过Executor 的工具类可以创建三种类型的普通线程池
a.FixThreadPool(int n);固定大小的线程池
使用于为了满足资源管理需求而需要限制当前线程数量的场合。使用于负载比较重的服务器。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Test {
public static void main(String[] args) {
ExecutorService ex=Executors.newFixedThreadPool(5);
for(int i=0;i<5;i++) {
ex.submit(new Runnable() {
@Override
public void run() {
for(int j=0;j<10;j++) {
System.out.println(Thread.currentThread().getName()+j);
}
}
});
}
ex.shutdown();
}
}
b.SingleThreadPoolExecutor:单线程池
需要保证顺序执行各个任务的场景
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Test {
public static void main(String[] args) {
ExecutorService ex=Executors.newSingleThreadExecutor();
for(int i=0;i<5;i++) {
ex.submit(new Runnable() {
@Override
public void run() {
for(int j=0;j<10;j++) {
System.out.println(Thread.currentThread().getName()+j);
}
}
});
}
ex.shutdown();
}
}
c.CashedThreadPool(); 缓存线程池
当提交任务速度高于线程池中任务处理速度时,缓存线程池会不断的创建线程
适用于提交短期的异步小程序,以及负载较轻的服务器
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Test {
public static void main(String[] args) {
ExecutorService ex=Executors.newCachedThreadPool();
for(int i=0;i<5;i++) {
ex.submit(new Runnable() {
@Override
public void run() {
for(int j=0;j<10;j++) {
System.out.println(Thread.currentThread().getName()+j);
}
}
});
}
ex.shutdown();
}
}
注意:多数情况下使用线程池来创建线程
下期见!!!