四种线程创建的方式

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

猜你喜欢

转载自blog.csdn.net/weixin_38004638/article/details/82829288