首页 > 编程语言 >java创建线程的4种方式

java创建线程的4种方式

时间:2024-01-19 10:36:08浏览次数:32  
标签:java Thread 创建 return static 线程 new public

1.Thread类

  • 一个线程在Java中使用一个Thread实例来描述。Thread类是Java语言一个重要的基础类,位于java.lang包中。Thread类有不少非常重要的属性和方法,用于存储和操作线程的描述信息。

image

1.1 线程ID

属性: private long tid,此属性用于保存线程的ID。这是一个private类型属性,外部只能使用getId()方法进行访问线程的ID.

方法: public long getld(),获取线程ID,线程ID由JVM进行管理,在进程内唯一。

1.2 线程名称

属性: private String name,该属性保存一个Thread线程实例的名字。
方法一: public final String getName(),获取线程名称。
方法二: public final void setName(String name),设置线程名称。
方法三: Thread(String threadName),通过此构造方法给线程设置一个定制化的名字。

1.3 线程优先级

属性: private int priority,保存一个Thread线程实例的优先级。
方法一: public final int getPriority(),获取线程优先级。
方法二: public final void setPriority(int priority),设置线程优先级。

  • Java线程优先级的最大值为10,最小值为1,默认值为5。这三个优先级值为三个常量值,也是在Thread类中使用类常量定义,三个类常量如下:
public static final int MIN_PRIORITY=1;
public static final int NORM_PRIORITY=5;
public static final int MAX_PRIORITY=10:

1.4 是否为守护线程

属性: private boolean daemon=false,该属性保存Thread线程实例的守护状态,默认为false,表示是普通的用户线程,而不是守护线程。
方法:public final void setDaemon(boolean on),将线程标记为守护线程或用户线程,如果参数值为true,那么将线程实例标记为守护线程。

1.5 线程的状态

属性: private int threadStatus,该属性以整数的形式保存线程的状态。

方法: public Thread.State getState(),返回表示当前线程的执行状态,为新建就绪运行阻塞结束等状态中的一种。

public enum State {
        NEW, // 新建
        RUNNABLE,// 就绪、运行
        BLOCKED,// 阻塞
        WAITING, // 等待
        TIMED_WAITING, // 计时等待
        TERMINATED; // 结束
    }
  • 在Java线程的状态中,就绪状态和运行状态在内部都用同一种状态RUNNABLE表示。就绪状态表示线程具备运行条件,正在等待获取CPU时间片:运行状态表示线程已经获取了CPU时间片,CPU正在执行线程代码逻辑。

1.6 线程的启动和运行

方法一: public void start(),用来启动一个线程,当调用start()方法后,JVM才会开启一个新的线程来执行用户定义的线程代码逻辑,在这个过程中会为相应的线程分配需要的资源。
方法二: public void run(),作为线程代码逻辑的入口方法。run()方法不是由用户程序来调用的,当调用start()方法启动一个线程之后,只要线程获得了CPU执行时间,便进入run()方法去执行具体的用户线程代码。

start()法用于线程的启动,run()方法作为用户代码逻辑的执行入口。

1.7 取得当前线程

方法: public static Thread currentThread(),该方法是一个非常重要的静态方法,用于获取当前线程的Thread实例对象。

什么是当前线程呢? 就是当前在CPU上执行的线程。在没有其他的途径获取当前线程的实例对象的时候,可以通过Thread.currentThread()静态方法获取。

2.创建线程的几种方式

2.1 继承 Thread 类创建线程类(方法1)

  1. 需要继承Thread类,创建一个新的线程类。
  2. 同时重写run()方法,将需要并发执行的业务代码编写在run()方法中。
public  class DemoThread extends Thread {
    	private static int threadNo = 0;
        public DemoThread() {
            super("Mall-" + threadNo++);
        }
        public void run() {
          // TODO
        }
 }    

2.2 实现 Runnable 接口创建线程(方法2)

  1. public Thread(Runnable target)
  2. public Thread(Runnable target, String name)
  3. public Thread(ThreadGroup group, Runnable target)
public class RunTarget implements Runnable {
    public void run() {
        // TODO
    }
    
    public static void main(String args[]){
        private static int threadNo = 0;
        Thread  thread = new Thread(new RunTarget(),"name" + threadNo++);
    }
    
}

2.3 Callable 和 FutureTask 系列接口

  • 继承Thread类或者实现Runnable接口这两种方式来创建线程类,不能获取异步执行的结果。
  • Java语言在1.5版本之后提供了一种新的多线程创建方法:通过Callable接口和FutureTask类相结合创建线程,解决异步执行的结果问题。

2.3.1 Callable接口

  • Callable接口是一个泛型接口,是一个函数式接口
  • 其唯一的抽象方法call()有返回值,返回值的类型为Callable接口的泛型形参类型。
  • call()抽象方法还有一个Exception的异常声明,容许方法的实现版本的内部异常直接抛出,并且可以不予捕获。

Callable实例能否和Runnable实例一样,作为Thread线程实例的target来使用呢?

答案是不行。Thread的target属性的类型为Runnable,而Callable接口与Runnable接口之间没有任何继承关系,并且二者唯一的方法在名字上也不同。显而易见,Callable接口实例没有办法作为Thread线程实例的target来使用。需要一个在Calable接口与Thread线程之间起到搭桥作用的重要接口。

@FunctionalInterface
public interface Callable<V> {
   
    V call() throws Exception;
}

2.3.2 RunnableFuture 接口

  • 该接口与Runnable接口、Thread类紧密相关。
  • 与Callable接口一样RunnableFuture接口也位于java.util.concurrent包中,使用时需要用import导入。
  • RunnableFuture是如何在Callable与Thread之间实现搭桥功能的呢? RunnableFuture接口实现了两个目标
    • 一是可以作为Thread线程实例的target实例,
    • 二是可以获取异步执行的结果。
public interface RunnableFuture<V> extends Runnable, Future<V> {
    void run();
}

RunnableFuture继承了Runnable接口,从而保证了其实例可以作为Thread线程实例的target日标;

同时,RunnableFuture通过继承Future接口,保证了通过它可以获取未来的异步执行结果。

2.3.3 Future 接口

Future接口至少提供了三大功能:

  1. 能够取消异步执行中的任务。
  2. 判断异步任务是否执行完成。
  3. 获取异步任务完成后的执行结果。
public interface Future<V> {
    boolean cancel(boolean mayInterruptIfRunning);
    boolean isCancelled();
    boolean isDone();
    V get() throws InterruptedException, ExecutionException;
    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

对Future接口的主要方法详细说明如下:

  • V get(): 获取异步任务执行的结果。注意,这个方法的调用是阻塞性的。如果异步任务没有执行完成,异步结果获取线程(调用线程)会一直被阻塞,一直阻塞到异步任务执行完成,其异步结果返回给调用线程。
  • V get(Long timeout,TimeUnitunit): 设置时限,(调用线程)阻塞性地获取异步任务执行的结果。该方法的调用也是阻塞性的,但是结果获取线程(调用线程)会有一个阻塞时长限制,不会无限制地阻塞和等待,如果其阻塞时间超过设定的timeout时间,该方法将抛出异常,调用线程可捕获此异常。
  • boolean isDone():获取异步任务的执行状态。如果任务执行结束,就返回true
  • boolean isCancelled():获取异步任务的取消状态。如果任务完成前被取消,就返回true。
  • boolean cancel(boolean mayInterruptRunning):取消异步任务的执行。

总体来说,Future是一个对异步任务进行交互、操作的接口。但是Future仅仅是一个接口,通过它没有办法直接完成对异步任务的操作,JDK提供了一个默认的实现类FutureTask

2.4 FutureTask 类

  • FutureTask类是Future接口的实现类,提供了对异步任务的操作的具体实现。
  • FutureTask类不仅仅实现了Future接口,还实现了Runnable接口,或者更加准确地说,FutureTask类实现了RunnableFuture接口。
  • RunnableFuture接口既可以作为Thread线程实例的target日标,也可以获取并发任务执行的结果,是ThreadCallable之间一个非常重要的搭桥角色。
  • RunnableFuture是一个接口,无法直接创建对象,如果需要创建对象,就需用到它的实现类FutureTask。所以说FutureTask类才是真正的在Thread与Callable之间搭桥的类。

image

FutureTask类的UML关系图可以看到:FutureTask实现了RunnableFuture接口,而RunnableFuture接口继承了Runnable接口和Future接口,所以FutureTask既能当作一个Runnable类型的target执行目标直接被Thread执行,又能作为Future异步任务来获取Callable的计算结果。

FutureTask如何完成多线程的并发执行、任务结果的异步获取呢?FutureTask内部有一个Callable类型的成员callable实例属性。

private Callable<V> callable;
  • callable 实例属性用来保存并发执行的Callable<V>类型的任务,并且callable实例属性需要在FutureTask实例构造时进行初始化。FutureTask类实现了Runnable接口,在其run()方法的实现版本中会执行callable成员的call()方法。
  • FutureTask内部还有另一个非常重要的Obiect 类型的成员outcome实例属性:
private Object outcome;
  • FutureTask的outcome实例属性用于保存callable成员call()方法的异步执行结果。在FutureTaskrun()方法完成callable成员的call()方法的执行之后,其结果将被保存在outcome实例属性中,供FutureTask类的get()方法获取。

2.5 Callable 和 FutureTask 创建线程(方法3)

通过FutureTask类和Callable接口的联合使用可以创建能获取异步执行结果的线程。具体步骤如下:

  1. 创建一个Callable接口的实现类,并实现其call()方法,编写好异步执行的具体逻辑,可以有返回值。
  2. 使用Callable实现类的实例构造一个FutureTask实例。
  3. 使用FutureTask实例作为Thread构造器的target入参,构造新的Thread线程实例。
  4. 调用Thread实例的start()方法启动新线程,启动新线程的run()方法并发执行。其内部的执行过程为:启动Thread实例的run()方法并发执行后,会执行FutureTask实例的run()方法,最终会并发执Callable实现类的call()方法。
  5. 调用FutureTask对象的get()方法阻塞性地获得并发线程的执行结果。
 public class ReturnableTask implements Callable<Long> {
        public Long call() throws Exception {
            long startTime = System.currentTimeMillis();
            Thread.sleep(1000);
           	// TODO 
            long used = System.currentTimeMillis() - startTime;
            return used;
        }
}


public class Demo {
    public static final int MAX_TURN = 5;
    public static final int COMPUTE_TIMES = 100000000;
        
    public static void main(String args[]) throws InterruptedException {
        // callable接口的具体实现
        ReturnableTask task = new ReturnableTask();
        // 传入callable接口
        FutureTask<Long> futureTask = new FutureTask<Long>(task);
        // 传入futureTask
        Thread thread = new Thread(futureTask, "returnableThread");
        thread.start(); 
        Thread.sleep(500);
       
        for (int i = 0; i < COMPUTE_TIMES / 2; i++) {
            int j = i * 10000;
        }
                
        try {
        	System.out.println(thread.getName() + "线程占用时间:" + futureTask.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

image

  • futureTask的结果outcome不为空,callable.call()执行完成。在这种情况下,futureTast.get会直接取回outcome结果,返回给main线程(结果获取线程)。
  • futureTask的结果outcome为空,callable.call()还没有执行完。在这种情况下,main线程作为结果获取线程会被阻塞住,一直被阻塞到callable.cal()执行完成。当执行完后,最终结果保存到outcome中,futureTask会唤醒main线程去提取callable.call()执行结果。

2.6 通过线程池创建线程(方法4)

  • 前三种方式所创建的Thread实例在执行完成之后都销毁了,这些线程实例都是不可复用的。
  • 实际上创建一个线程实例在时间成本、资源耗费上都很高的,在高并发的场景中,断然不能频繁进行线程实例的创建与销毁,而是需要对已经创建好的线程实例进行复用,Java中提供了一个静态工厂来创建不同的线程池,该静态工厂为Executors工厂类。
public class Executors {

    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

    public static ExecutorService newWorkStealingPool(int parallelism) {
        return new ForkJoinPool
            (parallelism,
             ForkJoinPool.defaultForkJoinWorkerThreadFactory,
             null, true);
    }

    public static ExecutorService newWorkStealingPool() {
        return new ForkJoinPool
            (Runtime.getRuntime().availableProcessors(),
             ForkJoinPool.defaultForkJoinWorkerThreadFactory,
             null, true);
    }

   public static ExecutorService newFixedThreadPool(int nThreads,ThreadFactory threadFactory) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>(),
                                      threadFactory);
    }

    public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

    public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>(),
                                    threadFactory));
    }
    
    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

    public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>(),
                                      threadFactory);
    }

    public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
        return new DelegatedScheduledExecutorService
            (new ScheduledThreadPoolExecutor(1));
    }
    
    public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory) {
        return new DelegatedScheduledExecutorService
            (new ScheduledThreadPoolExecutor(1, threadFactory));
    }

    public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }

    public static ScheduledExecutorService newScheduledThreadPool(
            int corePoolSize, ThreadFactory threadFactory) {
        return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
    }
    
    public static ExecutorService unconfigurableExecutorService(ExecutorService executor) {
        if (executor == null)
            throw new NullPointerException();
        return new DelegatedExecutorService(executor);
    }

    public static ScheduledExecutorService unconfigurableScheduledExecutorService(ScheduledExecutorService executor) {
        if (executor == null)
            throw new NullPointerException();
        return new DelegatedScheduledExecutorService(executor);
    }

    public static ThreadFactory defaultThreadFactory() {
        return new DefaultThreadFactory();
    }

    public static ThreadFactory privilegedThreadFactory() {
        return new PrivilegedThreadFactory();
    }

    public static <T> Callable<T> callable(Runnable task, T result) {
        if (task == null)
            throw new NullPointerException();
        return new RunnableAdapter<T>(task, result);
    }

    public static Callable<Object> callable(Runnable task) {
        if (task == null)
            throw new NullPointerException();
        return new RunnableAdapter<Object>(task, null);
    }

    public static Callable<Object> callable(final PrivilegedAction<?> action) {
        if (action == null)
            throw new NullPointerException();
        return new Callable<Object>() {
            public Object call() { return action.run(); }};
    }

    public static Callable<Object> callable(final PrivilegedExceptionAction<?> action) {
        if (action == null)
            throw new NullPointerException();
        return new Callable<Object>() {
            public Object call() throws Exception { return action.run(); }};
    }

    public static <T> Callable<T> privilegedCallable(Callable<T> callable) {
        if (callable == null)
            throw new NullPointerException();
        return new PrivilegedCallable<T>(callable);
    }

    public static <T> Callable<T> privilegedCallableUsingCurrentClassLoader(Callable<T> callable) {
        if (callable == null)
            throw new NullPointerException();
        return new PrivilegedCallableUsingCurrentClassLoader<T>(callable);
    }

    // Non-public classes supporting the public methods

    /**
     * A callable that runs given task and returns given result
     */
    static final class RunnableAdapter<T> implements Callable<T> {
        final Runnable task;
        final T result;
        RunnableAdapter(Runnable task, T result) {
            this.task = task;
            this.result = result;
        }
        public T call() {
            task.run();
            return result;
        }
    }

    /**
     * A callable that runs under established access control settings
     */
    static final class PrivilegedCallable<T> implements Callable<T> {
        private final Callable<T> task;
        private final AccessControlContext acc;

        PrivilegedCallable(Callable<T> task) {
            this.task = task;
            this.acc = AccessController.getContext();
        }

        public T call() throws Exception {
            try {
                return AccessController.doPrivileged(
                    new PrivilegedExceptionAction<T>() {
                        public T run() throws Exception {
                            return task.call();
                        }
                    }, acc);
            } catch (PrivilegedActionException e) {
                throw e.getException();
            }
        }
    }

    /**
     * A callable that runs under established access control settings and
     * current ClassLoader
     */
    static final class PrivilegedCallableUsingCurrentClassLoader<T> implements Callable<T> {
        private final Callable<T> task;
        private final AccessControlContext acc;
        private final ClassLoader ccl;

        PrivilegedCallableUsingCurrentClassLoader(Callable<T> task) {
            SecurityManager sm = System.getSecurityManager();
            if (sm != null) {
                // Calls to getContextClassLoader from this class
                // never trigger a security check, but we check
                // whether our callers have this permission anyways.
                sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);

                // Whether setContextClassLoader turns out to be necessary
                // or not, we fail fast if permission is not available.
                sm.checkPermission(new RuntimePermission("setContextClassLoader"));
            }
            this.task = task;
            this.acc = AccessController.getContext();
            this.ccl = Thread.currentThread().getContextClassLoader();
        }

        public T call() throws Exception {
            try {
                return AccessController.doPrivileged(
                    new PrivilegedExceptionAction<T>() {
                        public T run() throws Exception {
                            Thread t = Thread.currentThread();
                            ClassLoader cl = t.getContextClassLoader();
                            if (ccl == cl) {
                                return task.call();
                            } else {
                                t.setContextClassLoader(ccl);
                                try {
                                    return task.call();
                                } finally {
                                    t.setContextClassLoader(cl);
                                }
                            }
                        }
                    }, acc);
            } catch (PrivilegedActionException e) {
                throw e.getException();
            }
        }
    }

    /**
     * The default thread factory
     */
    static class DefaultThreadFactory implements ThreadFactory {
        private static final AtomicInteger poolNumber = new AtomicInteger(1);
        private final ThreadGroup group;
        private final AtomicInteger threadNumber = new AtomicInteger(1);
        private final String namePrefix;

        DefaultThreadFactory() {
            SecurityManager s = System.getSecurityManager();
            group = (s != null) ? s.getThreadGroup() :
                                  Thread.currentThread().getThreadGroup();
            namePrefix = "pool-" +
                          poolNumber.getAndIncrement() +
                         "-thread-";
        }

        public Thread newThread(Runnable r) {
            Thread t = new Thread(group, r,
                                  namePrefix + threadNumber.getAndIncrement(),
                                  0);
            if (t.isDaemon())
                t.setDaemon(false);
            if (t.getPriority() != Thread.NORM_PRIORITY)
                t.setPriority(Thread.NORM_PRIORITY);
            return t;
        }
    }

    /**
     * Thread factory capturing access control context and class loader
     */
    static class PrivilegedThreadFactory extends DefaultThreadFactory {
        private final AccessControlContext acc;
        private final ClassLoader ccl;

        PrivilegedThreadFactory() {
            super();
            SecurityManager sm = System.getSecurityManager();
            if (sm != null) {
                // Calls to getContextClassLoader from this class
                // never trigger a security check, but we check
                // whether our callers have this permission anyways.
                sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);

                // Fail fast
                sm.checkPermission(new RuntimePermission("setContextClassLoader"));
            }
            this.acc = AccessController.getContext();
            this.ccl = Thread.currentThread().getContextClassLoader();
        }

        public Thread newThread(final Runnable r) {
            return super.newThread(new Runnable() {
                public void run() {
                    AccessController.doPrivileged(new PrivilegedAction<Void>() {
                        public Void run() {
                            Thread.currentThread().setContextClassLoader(ccl);
                            r.run();
                            return null;
                        }
                    }, acc);
                }
            });
        }
    }

    /**
     * A wrapper class that exposes only the ExecutorService methods
     * of an ExecutorService implementation.
     */
    static class DelegatedExecutorService extends AbstractExecutorService {
        private final ExecutorService e;
        DelegatedExecutorService(ExecutorService executor) { e = executor; }
        public void execute(Runnable command) { e.execute(command); }
        public void shutdown() { e.shutdown(); }
        public List<Runnable> shutdownNow() { return e.shutdownNow(); }
        public boolean isShutdown() { return e.isShutdown(); }
        public boolean isTerminated() { return e.isTerminated(); }
        public boolean awaitTermination(long timeout, TimeUnit unit)
            throws InterruptedException {
            return e.awaitTermination(timeout, unit);
        }
        public Future<?> submit(Runnable task) {
            return e.submit(task);
        }
        public <T> Future<T> submit(Callable<T> task) {
            return e.submit(task);
        }
        public <T> Future<T> submit(Runnable task, T result) {
            return e.submit(task, result);
        }
        public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
            throws InterruptedException {
            return e.invokeAll(tasks);
        }
        public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
                                             long timeout, TimeUnit unit)
            throws InterruptedException {
            return e.invokeAll(tasks, timeout, unit);
        }
        public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
            throws InterruptedException, ExecutionException {
            return e.invokeAny(tasks);
        }
        public <T> T invokeAny(Collection<? extends Callable<T>> tasks,
                               long timeout, TimeUnit unit)
            throws InterruptedException, ExecutionException, TimeoutException {
            return e.invokeAny(tasks, timeout, unit);
        }
    }

    static class FinalizableDelegatedExecutorService
        extends DelegatedExecutorService {
        FinalizableDelegatedExecutorService(ExecutorService executor) {
            super(executor);
        }
        protected void finalize() {
            super.shutdown();
        }
    }

    /**
     * A wrapper class that exposes only the ScheduledExecutorService
     * methods of a ScheduledExecutorService implementation.
     */
    static class DelegatedScheduledExecutorService
            extends DelegatedExecutorService
            implements ScheduledExecutorService {
        private final ScheduledExecutorService e;
        DelegatedScheduledExecutorService(ScheduledExecutorService executor) {
            super(executor);
            e = executor;
        }
        public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
            return e.schedule(command, delay, unit);
        }
        public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) {
            return e.schedule(callable, delay, unit);
        }
        public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) {
            return e.scheduleAtFixedRate(command, initialDelay, period, unit);
        }
        public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) {
            return e.scheduleWithFixedDelay(command, initialDelay, delay, unit);
        }
    }

    /** Cannot instantiate. */
    private Executors() {}
}

2.6.1 线程池的创建与执行目标提交

  • 通过 Executors 工厂类创建一个线程池,一个简单的示例如下:
//创建一个包含三个线程的线程池
private static ExecutorService pool = Executors.newFixedThreadPool(3);
  1. 工厂类Executors的newFixedThreadPool(int threads)方法创建了一个线程池,所创建的线程池的类型为ExecutorService

  2. 工厂类的newFixedThreadPool(int threads)方法用于创建包含一个固定数目的线程池。ExecutorService是Java提供的一个线程池接口,每次我们在异步执行target目标任务的时候,可以通过ExecutorService线程池实例去提交或者执行。

  3. ExecutorService实例负责对池中的线程进行管理和调度,并且可以有效控制最大并发线程数,提高系统资源的使用率,同时提供定时执行、定频执行、单线程、并发数控制等功能。

ExecutorService线程池提交异步执行target日标任务的常用方法有:

//方法一:执行一个 Runnable类型的target执行目标实例,无返回
void execute(Runnable command);

//方法二:提交一个 Callable类型的target执行目标实例,返回一个Future异步任务实例
<T> Future<T> submit(Callable<T>task);

//方法三:提交一个 Runnable类型的target执行目标实例,返回一个Future异步任务实例
Future<?>submit(Runnable task);

2.6.2 线程池的使用

public class Demo {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //创建一个包含三个线程的线程池
        ExecutorService pool = Executors.newFixedThreadPool(3);

        pool.execute(new DemoThread()); //执行线程实例
        //执行Runnable执行目标实例
        pool.execute(new Runnable() {
            @Override
            public void run() {
                for (int j = 1; j < MAX_TURN; j++) {
                   // TODO
                }
            }
        });
        //提交Callable 执行目标实例
        Future future = pool.submit(new ReturnableTask());
        Long result = (Long) future.get();
        System.out.println(("异步任务的执行结果为:" + result);
    }

    static class DemoThread implements Runnable {
        @Override
        public void run() {
            for (int j = 1; j < MAX_TURN; j++) {
              // TODO
            }
        }
    }

    public static final int MAX_TURN = 5;
    public static final int COMPUTE_TIMES = 100000000;

    static class ReturnableTask implements Callable<Long> {
        //返回并发执行的时间
        public Long call() throws Exception {
            long startTime = System.currentTimeMillis();
          	// TODO
            long used = System.currentTimeMillis() - startTime;
            return used;
        }
    }
}

2.6.3 submit 和 execute区别

  1. 接收的参数不一样
    submit()可以接受两种入参:
    • 无返回值的Runnable类型的target执行目标实例。
    • 有返回值Callable类型的target执行目标实例。
    • execute()仅仅接收无返回值的target执行目标实例,或者无返回值的Thread实例。
  2. submit()有返回值,而execute()没有
    • submit()方法在提交异步target执行目标之后会返回Future异步任务实例,以对target的异步执行过程进行控制,比如取消执行、获取结果等。
    • execute()没有任何返回,target执行目标实例在执行之后没有办法对其异步执行过程进行控制,只能任其执行,直到其执行结束。

标签:java,Thread,创建,return,static,线程,new,public
From: https://www.cnblogs.com/ccblblog/p/17974066

相关文章

  • SQLServer创建用户后无法登录,报错18456的解决方式
    原因:SQLServer没有设置为混合模式。解决方法:服务器本地通过Windows验证,打开SQLServer右键服务器,选择安全性,选择为混合验证模式,然后重启SQLServer服务即可。......
  • Java里ArrayList中的toArray()用法
    深入理解List的toArray()方法和toArray(T[]a)方法这两个方法都是将列表List中的元素转导出为数组,不同的是,toArray()方法导出的是Object类型数组,而toArray[T[]a]方法导出的是指定类型的数组。下面是两个方法的申明及说明,摘自Java8的API文档。toArray()方法的分析Object[]toA......
  • 基于JAVA的新闻类网站
    21世纪的今天,随着社会的不断发展与进步,人们对于信息科学化的认识,已由低层次向高层次发展,由原来的感性认识向理性认识提高,管理工作的重要性已逐渐被人们所认识,科学化的管理,使信息存储达到准确、快速、完善,并能提高工作管理效率,促进其发展。论文主要是对新闻类网站进行了介绍,包括研......
  • 论文翻译 | 【深入挖掘Java技术】「底层原理专题」深入分析一下并发编程之父Doug Lea
    前提介绍DougLea在州立大学奥斯威戈分校(DougLea)摘要本文深入探讨了一个Java框架的设计、实现及其性能。该框架遵循并行编程的理念,通过递归方式将问题分解为多个子任务,并利用工作窃取技术进行并行处理。所有子任务完成后,其结果被整合以形成完整的并行程序。在总体设计上,该框架借鉴......
  • javascript中的undefined可以被重写
    众所周知,当声明一个变量,并且没有给赋值的情况下,它的初始值是 undefined。但是在javascript中,怎么检查一个值是否为 undefined 呢?在现代浏览器中,你可以安全的直接比较将变量是与 undefined 进行比较if(name===undefined){//...}一些人反对直接使用 undefined......
  • 深入理解Java中的ThreadLocal
    第1章:引言大家好,我是小黑。今天咱们来聊聊ThreadLocal。首先,让咱们先搞清楚,ThreadLocal是个什么玩意儿。简单说,ThreadLocal可以让咱们在每个线程中创建一个变量的“私有副本”。这就意味着,每个线程都可以独立地改变自己的副本,而不会影响其他线程。这就像是每个人都有自己的笔记......
  • 【APP逆向09】Java基础之数据类型(Map)
    1.Map是一个接口,常见实现这个接口的有两个类,用于存储键值对。HashMap,无序。TreeMap,默认根据key排序。(常用)2.实例2.1:HashMapimportjava.util.HashMap;publicclassDemo7{publicstaticvoidmain(String[]args){HashMaph1=newHashMap();......
  • Java 线程池
    Java线程池前言:创建过多的线程会占用更多的内存、并且在线程切换的时候增加消耗的资源和浪费更多的时间,为了缓解以上问题,出现一种基于复用和预分配思想的技术,线程池。线程池中的线程被统一创建和管理,提高了系统响应时间和系统的资源利用率。除了线程池解决以上问题外,在java21......
  • 初识Java
    初识Java一场旷日持久的战争故事:Java帝国的诞生C&C++1972年C诞生贴近硬件,运行极快,效率极高。操作系统,编译器,数据库,网络系统等指针和内存管理1982年C++诞生面向对象兼容C图形领域、游戏等反抗我们要建立一个新的语言:语法有点像C没有指......
  • Js(Javascript)的apply call 和bind区别
    ​ apply、call和bind是用于调用函数的三种不同方式,它们的主要区别在于函数调用时的上下文(this关键字)以及参数传递的方式。call和apply是用于立即调用函数并设置this上下文的方法,它们的主要区别在于参数传递的方式。bind不会立即执行函数,而是创建一个新的函数,将this......