Four ways to create thread thread, runable, callable, and ExecutorService

Four ways to create threads

1. Inherit the Thread class
2. Implement the Runnable class
3. Implement the Callable class
4. Create a thread through the thread pool: A thread queue is provided, in which all threads in the waiting state are stored. Avoid creation and destruction of extra overhead, improve the speed of response

Architecture:
java.util.concurrent.Executor: the root interface responsible for the use and scheduling of threads
|–ExecutorService subinterface: the main interface of
thread pool|–ThreadPoolExecutor implementation class of thread pool
|–ScheduledExecutorService subinterface: responsible for thread scheduling
| -ScheduledThreadPoolExecutor: inherit ThreadPoolExecutor, implement ScheduledExecutorService *

Tools: Executors
ExecutorService newFixedThreadPool(): Create a fixed-size thread pool
ExecutorService newCachedThreadPool(): Cache thread pool. The number of thread pools is not fixed, and the number can be changed automatically according to demand.
ExecutorService newSingleThreadExecutor(): Create a single thread pool. There is only one thread in the thread pool.
ScheduledExecutorService newScheduledThreadPool(): Create a fixed-size thread that can execute tasks in a delayed or timed manner.

details as follows:

One, inherit the Thread class

The steps to create a thread by inheriting the Thread class are:
(1) Create a class to inherit the Thread class, rewrite the run() method, and write the code of the task to be completed into the run() method;
(2) Create a subclass of the Thread class Object;
(3) Call the start() method of the object, the start() method means to start the thread first, and then call the run() method;

public class ThreadTest {
    public static void main(String[] args) {
        window t1 = new window();
        window1 t2 = new window1();
        t1.setName("售票口1");
        t2.setName("售票口2");
        t1.start();
        t2.start();
        if(t1.isInterrupted() == true){
            t1.interrupt();
            System.out.println("线程1停止");
        }
    }
    static class window extends Thread{
       //将其加载在类的静态区,所有线程共享该静态变量
        private static int ticket = 10; 
        @Override
        public synchronized void run() {
            while(true){
                if(ticket>0){
                    try {
                        sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(getName()+"当前售出第"+ticket+"张票");
                    ticket--;
                }else{
                    interrupt();
                    System.out.println("1正在判断线程是否终止"+isInterrupted());
                    break;
                }
                System.out.println("1正在判断线程是否终止@@"+isInterrupted());
            }
        }
    }

   static class window1 extends Thread{
     //将其加载在类的静态区,所有线程共享该静态变量
        private static int ticket = 5; 
        @Override
        public synchronized void run() {
            while(true){
                if(ticket>0){
                    System.out.println(getName()+"当前售出第"+ticket+"张票");
                    try {
                        sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    ticket--;
                }else{
                    interrupt();
                    System.out.println("2正在判断线程是否终止"+isInterrupted());
                    break;
                }
                System.out.println("2正在判断线程是否终止"+isInterrupted());
            }
        }
    }
 }

Thread modifier, return type, method and description:

修饰符、返回类型、方法和说明
static int	activeCount()
返回当前线程的线程组及其子组中活动线程的数量的估计值。
void	checkAccess()
确定当前正在运行的线程是否有权修改此线程。
protected Object	clone()
抛出CloneNotSupportedException,因为无法有意义地克隆线程。
int	countStackFrames()
不推荐使用。 
此调用的定义取决于suspend()已弃用的。此外,此调用的结果从未明确定义。
static Thread	currentThread()
返回对当前正在执行的线程对象的引用。
void	destroy()
不推荐使用。 
此方法最初设计为在不进行任何清理的情况下破坏此线程。它所持有的任何监视器都将保持锁定状态。但是,该方法从未实现。如果要实施,那么它在很大程度上将很容易死锁suspend()。如果目标线程在销毁关键系统资源时持有锁来保护它,则任何线程都无法再次访问该资源。如果另一个线程曾试图锁定此资源,则将导致死锁。这种僵局通常表现为“冻结”进程。有关更多信息,请参见 为什么不赞成使用Thread.stop,Thread.suspend和Thread.resume?。
static void	dumpStack()
将当前线程的堆栈跟踪记录打印到标准错误流。
static int	enumerate(Thread[] tarray)
将当前线程的线程组及其子组中的每个活动线程复制到指定的数组中。
static Map<Thread,StackTraceElement[]>	getAllStackTraces()
返回所有活动线程的堆栈跟踪的映射。
ClassLoader	getContextClassLoader()
返回此线程的上下文ClassLoader。
static Thread.UncaughtExceptionHandler	getDefaultUncaughtExceptionHandler()
返回由于未捕获的异常导致线程突然终止时调用的默认处理程序。
long	getId()
返回此线程的标识符。
String	getName()
返回此线程的名称。
int	getPriority()
返回此线程的优先级。
StackTraceElement[]	getStackTrace()
返回表示该线程的堆栈转储的堆栈跟踪元素的数组。
Thread.State	getState()
返回此线程的状态。
ThreadGroup	getThreadGroup()
返回该线程所属的线程组。
Thread.UncaughtExceptionHandler	getUncaughtExceptionHandler()
返回此线程由于未捕获的异常而突然终止时调用的处理程序。
static boolean	holdsLock(Object obj)
当且仅当当前线程在指定对象上持有监视器锁时,才返回true。
void	interrupt()
中断此线程。
static boolean	interrupted()
测试当前线程是否已被中断。
boolean	isAlive()
测试此线程是否仍然存在。
boolean	isDaemon()
测试此线程是否是守护程序线程。
boolean	isInterrupted()
测试此线程是否已被中断。
void	join()
等待该线程死亡。
void	join(long millis)
等待最多millis毫秒,直到该线程消失。
void	join(long millis, int nanos)
等待最多millis毫秒加 nanos十亿分之一秒的时间,以使该线程死亡。
void	resume()
不推荐使用。 
该方法仅适用于与suspend(),因为它容易死锁,因此已弃用。有关更多信息,请参见 为什么不赞成使用Thread.stop,Thread.suspend和Thread.resume?。
void	run()
如果此线程是使用单独的 Runnable运行对象构造的,则调用该Runnable对象的run方法;否则,将调用该 对象的方法。否则,此方法不执行任何操作并返回。
void	setContextClassLoader(ClassLoader cl)
设置此线程的上下文ClassLoader。
void	setDaemon(boolean on)
将此线程标记为守护程序线程或用户线程。
static void	setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)
设置当线程由于未捕获的异常而突然终止并且没有为该线程定义其他处理程序时调用的默认处理程序。
void	setName(String name)
将此线程的名称更改为等于参数 name。
void	setPriority(int newPriority)
更改此线程的优先级。
void	setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)
设置当此线程由于未捕获的异常突然终止时调用的处理程序。
static void	sleep(long millis)
根据系统计时器和调度程序的精度和准确性,使当前正在执行的线程进入休眠状态(暂时停止执行)达指定的毫秒数。
static void	sleep(long millis, int nanos)
根据系统计时器和调度程序的精度和准确性,使当前正在执行的线程进入休眠状态(暂时停止执行)达指定的毫秒数加上指定的纳秒数。
void	start()
使该线程开始执行;Java虚拟机将调用run此线程的方法。
void	stop()
不推荐使用。 
这种方法本质上是不安全的。使用Thread.stop停止线程会导致它解锁所有已锁定的监视器(由于未经检查的ThreadDeath异常会自然 传播堆栈)。如果先前由这些监视器保护的任何对象处于不一致状态,则损坏的对象将变为其他线程可见,从而可能导致任意行为。的许多用途stop应该用简单地修改一些变量以指示目标线程应该停止运行的代码代替。目标线程应定期检查此变量,如果该变量指示它将停止运行,则应有序地从其运行方法返回。如果目标线程等待很长时间(例如,在条件变量上),interrupt则应使用该方法来中断等待。有关更多信息,请参见 为什么不赞成使用Thread.stop,Thread.suspend和Thread.resume?。
void	stop(Throwable obj)
不推荐使用。 
这种方法本质上是不安全的。有关stop() 详细信息,请参见。此方法的另一个危险是,它可能会用于生成目标线程不准备处理的异常(包括如果该方法不支持该线程,则可能无法抛出的已检查异常)。有关更多信息,请参见 为什么不赞成使用Thread.stop,Thread.suspend和Thread.resume?。
void	suspend()
不推荐使用。 
此方法已被弃用,因为它固有地容易死锁。如果目标线程在挂起时在监视器上持有锁以保护关键系统资源,则在恢复目标线程之前,没有线程可以访问该资源。如果将恢复目标线程的线程在调用之前尝试锁定此监视器resume,则会导致死锁。这种僵局通常表现为“冻结”进程。有关更多信息,请参见 为什么不赞成使用Thread.stop,Thread.suspend和Thread.resume?。
String	toString()
返回此线程的字符串表示形式,包括线程的名称,优先级和线程组。
static void	yield()
向调度程序提示当前线程愿意放弃当前使用的处理器。

Second, implement the Runnable class

The steps to implement the Runnable class to create a thread are:
(1) Create a class to implement the Runnable class, rewrite the run() method, and write the code of the task to be completed into the run() method;
(2) Create a subclass of the Runnable class Object;
(3) You need to first instantiate a Thread and pass in your own MyRunnable instance.
(4) Call the object's start() method. The start() method means to start the thread first, and then call the run() method;

public class TestRunnable {
    public static void main(String[] args) {
		MyRunnable myRunnable = new MyRunnable ();
		new Thread(myRunnable).start();
	}
}
 
class MyRunnable implements Runnable{
	@Override
	public void run() {
		boolean flag = false;
		for(int i  = 3 ; i < 100 ; i ++) {
			flag = false;
			for(int j = 2; j <= Math.sqrt(i) ; j++) {
				if(i % j == 0) {
					flag = true;
					break;
				}
			}
			if(flag == false) {
				System.out.print(i+"  ");
			}
		}
	}

operation result:

3  5  7  11  13  17  19  23  29  31  37  41  43  47  53  59  61  67  71  73  79  83  89  97

All known sub-interfaces:
RunnableFuture, RunnableScheduledFuture
V-the result type returned by the get method of this Future

You can also start the thread directly by d executor.execute(new RunnableTask1()) of ExecutorService

Third, implement the Callable class

The steps to implement the Callable class to create a thread are:
(1) Create a class to implement the Callable class, rewrite the run() method, and write the code of the task to be completed into the run() method, which can have a thread with a return value;
(2) Create an object of a subclass of the Callable class;
(3) You need to first instantiate a FutureTask and pass in your own myCallable instance
(4) You need to first instantiate a Thread and pass in your own FutureTask instance
(5) Call the object start() method, the start() method means to start the thread first, and then call the run() method;

Benefit : You can call the
get() method of FutureTask to get the return value. Because this method is blocking, it has been waiting for the thread to complete, sometimes it takes a long time. So sometimes it is necessary to set the timeout period.
get(long var1, TimeUnit var3) The first parameter of this method is a long integer number, and the second parameter is the unit
cancel (boolean mayInterruptIfRunning). Cancel the task,
pass true, the running task will be canceled, if successful, return true, fail Return false;
pass false to only cancel unstarted tasks, and running tasks will run successfully.
The isCancelled method indicates whether the task is canceled successfully, if it is canceled successfully before the task is completed normally, it returns true.
The isDone method indicates whether the task has been completed, if the task is completed, it returns true;

public class TestCallable {
    public static void main(String[] args) {

        MyCallable myCallable = new MyCallable();
        //FutureTask<Integer>是一个包装器,它通过接受Callable<Integer>来创建,它同时实现了Future和Runnable接口。
        FutureTask futureTask = new FutureTask(myCallable);
        Thread thread =new Thread(futureTask);
        thread.start();
    }

    static class MyCallable implements Callable{

        List<Object> list = new ArrayList<>();
        @Override
        public Object call() throws Exception {
            boolean flag = false;
            for(int i  = 3 ; i < 100 ; i ++) {
                flag = false;
                for(int j = 2; j <= Math.sqrt(i) ; j++) {
                    if(i % j == 0) {
                        flag = true;
                        break;
                    }
                }
                if(flag == false) {
                    System.out.print(i+"  ");
                   list.add(i);
                }
            }
            return list;
        }
    }
}

operation result:

3  5  7  11  13  17  19  23  29  31  37  41  43  47  53  59  61  67  71  73  79  83  89  97

Fourth, the way to create a thread pool

The steps of thread pool creation are:
(1) First create an ExecutorService of the thread pool,
(2) Instantiate a Callable object, and rewrite the call() method, which can have a return value;
(3) Call executorService.submit(callable) ) This method returns a Future object, which can be used to receive the results of multi-threaded execution.
Or the executorService.execute(myRunnale) method returns a Future object, which can be used to receive the execution results of multiple threads.

Benefit : You can call the
get() method of Future to get the return value, then because this method is blocking, it has been waiting for the thread to complete, sometimes it takes a long time. So sometimes it is necessary to set the timeout period.
get(long var1, TimeUnit var3) The first parameter of this method is a long integer number, and the second parameter is the unit
cancel (boolean mayInterruptIfRunning). Cancel the task,
pass true, the running task will be canceled, if successful, return true, fail Return false;
pass false to only cancel unstarted tasks, and running tasks will run successfully.
The isCancelled method indicates whether the task is canceled successfully, if it is canceled successfully before the task is completed normally, it returns true.
The isDone method indicates whether the task has been completed, if the task is completed, it returns true;

public class CallableTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //创建一个线程池
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        Callable<String> callable = new Callable<String>() {
            @Override
            public String call() throws Exception {
                Thread.sleep(3000);
                System.out.println("线程执行中..........");
                return "执行完毕";
            }
        };
        System.out.println("线程执行之前 "+TimeFormat());
        Future<String> future = executorService.submit(callable);
        System.out.println("线程开启之后 "+TimeFormat());
        //get方法会形成阻塞
//        System.out.println("获取返回值"+ future.get());
        try {
            future.get(2,TimeUnit.SECONDS);
        } catch (TimeoutException e) {
            e.printStackTrace();
            System.out.println("时间超时,舍弃。。。。");
        }
        System.out.println("获取结果之后 "+TimeFormat());
        System.out.println("线程是否结束1 "+future.isDone());
        System.out.println("线程是否完成前被取消1 "+future.isCancelled());
        Boolean oo = future.cancel(true);
        System.out.println("线程是否结束2 "+oo);
        System.out.println("线程是否结束3 "+future.isDone());
        System.out.println("线程是否完成前被取消3 "+future.isCancelled());
    }
    
    private static String TimeFormat(){
        Date now = new Date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss");
        return simpleDateFormat.format(now);
    }
}

operation result:

线程执行之前 16:35:52
线程开启之后 16:35:52
java.util.concurrent.TimeoutException
	at java.util.concurrent.FutureTask.get(FutureTask.java:205)
	at CallableTest.main(CallableTest.java:24)
时间超时,舍弃。。。。
获取结果之后 16:35:55
线程是否结束1 false
线程是否完成前被取消1 false
线程是否结束2 true
线程是否结束3 true
线程是否完成前被取消3 true
线程是否结束4 false

The timeout of TimeoutException is because the timeout period of 2 seconds needs to be set in the get() method, and the thread sleeps for 3 seconds, so it is directly discarded and no result is returned.

Future is an interface. Future represents the result of an asynchronous task that may not be completed. For this result, a Callback can be added to perform corresponding operations after the task execution succeeds or fails.
All methods eventually transform runnable or callable into a RunnableFuture object. This RunnableFutre object is an interface that inherits both Runnable and Future.

public interface RunnableFuture<V> extends Runnable, Future<V> {
    void run();
}

Then call the executor(runnable) method. Finally, a RunnableFuture object is returned. The interface RunnableFuture has a specific implementation class,

public class FutureTask<V> implements RunnableFuture<V>

FutureTask implements the RunnableFuture interface, since we know that the final return is a FutureTask object ftask, and we can get the return value of execute(task) through ftask.get().

Four implementation methods and principles of thread pool

Inadequacies, please advise! ! !

Guess you like

Origin blog.csdn.net/qq_41587243/article/details/105935364