四种线程创建的方式
1、通过实现Runnable接口来创建Thread线程:
class SomeRunnable implements Runnable{ // 步骤1:创建实现Runnable接口的类
public void run(){}
}
Runnable oneRunnable = new SomeRunnable(); //步骤2:创建一个类对象
Thread oneThread = new Thread(oneRunnable); //步骤3:由Runnable创建一个Thread对象
oneThread.start(); //步骤4:启动线程
注:当执行代码oneThread.start();时,就会执行oneRunnable对象中的void run();方法,该方法执行完成后,线程就消亡了。
package com.thread;
/**
* 作为线程任务存在
* @author chenyy
*
*/
public class Demo2 implements Runnable{
@Override
public void run() {
System.out.println("线程已经开始。。。。");
}
public static void main(String[] args){
Thread thread = new Thread(new Demo2());
thread.start();
}
}
2、通过实现Callable接口来创建Thread线程:
public interface Callable<V> {
V call() throws Exception;
}
class SomeRunnable implements Callable{ // 步骤1:创建实现Callable接口的类SomeCallable<Integer>
public void call(){}
}
Callable<Integer> oneCallable = new SomeCallable<Integer>(); //步骤2:创建一个类对象
FutureTask<Integer> oneTask = new FutureTask<Integer>(oneCallable); //步骤3:创建一个FutureTask<Integer>对象
//FutureTask<Integer>是一个包装器,它通过接受Callable<Integer>来创建,它同时实现了Future和Runnable接口。
Thread oneThread = new Thread(oneTask); //步骤4:由FutureTask<Integer>创建一个Thread对象
oneThread.start(); //步骤5:启动线程
//注:extends Thread 和 implements Runnable的run方法是由线程直接调用的,是异步执行的,而call方法是被future调用的,不是异步执行
package com.thread;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import com.sun.javafx.tk.Toolkit.Task;
import com.sun.jndi.url.dns.dnsURLContext;
public class Demo4 implements Callable<Integer>{
public static void main(String[] args) throws InterruptedException, ExecutionException{
Demo4 d = new Demo4();
FutureTask<Integer> task = new FutureTask<Integer>(d);
Thread thread = new Thread(task);
thread.start();
System.out.println(task.get());
}
@Override
public Integer call() throws Exception {
// TODO Auto-generated method stub
System.out.println("正在紧张的进行");
return 1;
}
}
3、通过继承Thread类来创建一个线程:
class SomeThead extends Thraad{ //步骤1:定义一个继承Thread类的子类
public void run(){ }
}
SomeThread oneThread = new SomeThread(); //步骤2:构造子类的一个对象
oneThread.start(); /步骤3:启动线程
package com.thread;
public class Demo1 extends Thread{
public Demo1(String name) {
super(name);
}
@Override
public void run() {
System.out.println(getName() + "线程执行了。。。");
}
public static void main(String[] args){
Demo1 d1 = new Demo1("first-thread");
Demo1 d2 = new Demo1("second-thread");
d1.start();
d2.start();
}
}
4、使用Executor框架来创建线程池
在Java 5之后,并发编程引入Executor框架,其内部使用了线程池机制,它在java.util.cocurrent 包下,通过该框架来控制线程的启动、执行和关闭,可以简化并发编程的操作。更易管理,效率更好(用线程池实现,节约开销)外,有助于避免this逃逸问题——如果我们在构造器中启动一个线程,因为另一个任务可能会在构造器结束之前开始执行,此时可能会访问到初始化了一半的对象用Executor在构造器中。
Executor框架包括:线程池,Executor,Executors,ExecutorService,CompletionService,Future,Callable等。
Executor接口中之定义了一个方法execute(Runnable command),该方法接收一个Runable实例,它用来执行一个任务,任务即一个实现了Runnable接口的类。ExecutorService接口继承自Executor接口,它提供了更丰富的实现多线程的方法,比如,ExecutorService提供了关闭自己的方法,以及可为跟踪一个或多个异步任务执行状况而生成 Future 的方法。 可以调用ExecutorService的shutdown()方法来平滑地关闭 ExecutorService,调用该方法后,将导致ExecutorService停止接受任何新的任务且等待已经提交的任务执行完成(已经提交的任务会分两类:一类是已经在执行的,另一类是还没有开始执行的),当所有已经提交的任务执行完毕后将会关闭ExecutorService。因此我们一般用该接口来实现和管理多线程。
ExecutorService的生命周期包括三种状态:运行、关闭、终止。创建后便进入运行状态,当调用了shutdown()方法时,便进入关闭状态,此时意味着ExecutorService不再接受新的任务,但它还在执行已经提交了的任务,当素有已经提交了的任务执行完后,便到达终止状态。如果不调用shutdown()方法,ExecutorService会一直处在运行状态,不断接收新的任务,执行新的任务,服务器端一般不需要关闭它,保持一直运行即可。
Executors提供了一系列工厂方法用于创先线程池,返回的线程池都实现了ExecutorService接口。
public static ExecutorService newFixedThreadPool(int nThreads) //创建固定数目线程的线程池。
public static ExecutorService newCachedThreadPool() //创建一个可缓存的线程池,调用execute将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线 程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。
public static ExecutorService newSingleThreadExecutor() //创建一个单线程化的Executor。
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) //创建一个支持定时及周期性的任务执行的线程池,多数情况下可用来替代Timer类。
//线程池的几种常见的创建的方式:https://blog.csdn.net/m0_37499059/article/details/79431706
-
一:创建大小不固定的线程池
-
二:创建固定数量线程的线程池
-
三:创建单线程的线程池
-
四:创建定时线程
1.创建大小不固定的线程池
package com.peace.pms.Test;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolDemo {
public static class Taskdemo implements Runnable{
@Override
public void run() {
for(int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
public static void main(String[] args) {
ExecutorService es=Executors.newFixedThreadPool(2);
for(int i=0;i<10;i++){
Taskdemo tc=new Taskdemo();
es.execute(tc);
}
es.shutdown();
}
}
2.创建固定数量线程的线程池
public static void main(String[] args) {
ExecutorService es=Executors.newFixedThreadPool(2);
for(int i=0;i<10;i++){
Taskdemo tc=new Taskdemo();
es.execute(tc);
}
es.shutdown();
}
3.创建单线程的线程池
public static void main(String[] args) {
ExecutorService es=Executors.newSingleThreadExecutor();
for(int i=0;i<10;i++){
Taskdemo tc=new Taskdemo();
es.execute(tc);
}
es.shutdown();
}
4.创建定时线程
public static void main(String[] args) {
ScheduledExecutorService es=Executors.newScheduledThreadPool(2);
for(int i=0;i<10;i++){
Taskdemo tc=new Taskdemo();
//参数1:目标对象
//参数2:隔多长时间开始执行线程,
//参数3:执行周期
//参数4:时间单位
es.scheduleAtFixedRate(tc, 30, 10, TimeUnit.MILLISECONDS);
}
es.shutdown();
}
上一篇: map遍历的四种方式
下一篇: vue组件间的通信方式