欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

四种线程创建的方式

程序员文章站 2022-05-15 18:38:48
...

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. 一:创建大小不固定的线程池

  2. 二:创建固定数量线程的线程池

  3. 三:创建单线程的线程池

  4. 四:创建定时线程

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();
    }