[JAVA concurrency] basic thread mechanism, java concurrent thread

Source: Internet
Author: User

[JAVA concurrency] basic thread mechanism, java concurrent thread
Basic thread Mechanism

A program can be divided into multiple independent tasks, and each independent task can be executed by a thread;

A process can contain several threads, that is, a number of concurrent tasks. When the program is running, the CPU time is divided into segments and allocated to all threads;

Multithreading on a single-processor machine can improve performance because of task blocking;

Adding a processor to the machine can significantly speed up the use of multi-threaded programs;

The thread mechanism is used to make the program more transparent and scalable, and the Code does not need to know whether it is running on a single processor or multi-processor;

Thread creation method 1. Create a task class to implement the Runnable interface and submit the specific object to the Thread constructor.

Create a launch class LiftOff to implement the Runnable interface:

Package concurrency; public class LiftOff implements Runnable {protected int countDown = 10; // Default private static int taskCount = 0; private final int id = taskCount ++; public LiftOff () {} public LiftOff (int countDown) {this. countDown = countDown;} public String status () {return Thread. currentThread () + "#" + id + "(" + (countDown> 0? CountDown: "Liftoff! ") +"), ";} Public void run () {while (countDown --> 0) {System. out. println (status (); Thread. yield ();}}}View Code

The preceding Code calls the Thread. yield () method. It is recommended that the Thread scheduler switch to another Thread to execute the task. Note that it is only recommended and cannot be accepted;

After creating the task class, you can use the LiftOff object in the Main function to create a Thread object and call its start method to start the Thread, as shown below:

package concurrency;public class BasicThreads {    public static void main(String[] args) {        Thread t = new Thread(new LiftOff());        t.start();        System.out.println(Thread.currentThread() + "Waiting for LiftOff");    }} 

The output is as follows. Note that two threads (main and Thread-0) are running in the program;

In addition, the Thread object is printed in the form of [Thread-0, 5, main], which in turn represents [Thread name, Thread priority, Thread group name], for details, see the toString method of the Thread class;

Thread[main,5,main]Waiting for LiftOffThread[Thread-0,5,main]#0(9), Thread[Thread-0,5,main]#0(8), Thread[Thread-0,5,main]#0(7), Thread[Thread-0,5,main]#0(6), Thread[Thread-0,5,main]#0(5), Thread[Thread-0,5,main]#0(4), Thread[Thread-0,5,main]#0(3), Thread[Thread-0,5,main]#0(2), Thread[Thread-0,5,main]#0(1), Thread[Thread-0,5,main]#0(Liftoff!), 

Finally, some people directly create a task class object in the main function after creating the task class and call its run method. The following code runs normally, I also saw the running result in the run method and thought that the thread was created. In fact, this usage method is incorrect and no new thread was created, only the method of executing a common object is called in the main thread;

package concurrency;public class MainThread {    public static void main(String[] args) {        LiftOff launch = new LiftOff();        launch.run();    }} 
Method 2: Inherit the Thread class and call the start method package concurrency of the specific object; public class SimpleThread extends Thread {private int countDown = 5; private static int threadCount = 0; public SimpleThread () {// Store the thread name: super (Integer. toString (++ threadCount); start ();} public String toString () {return "#" + getName () + "(" + countDown + "),";} public void run () {while (true) {System. out. println (this); if (-- countDown = 0) return ;}} public static void main (String [] args) {for (int I = 0; I <5; I ++) new SimpleThread ();}}View Code

This method is not recommended for implementing the Runnable interface, Because java's single Inheritance Mechanism is generally better than inheritance by implementing interfaces;

In addition, you can use internal classes to hide thread code in the class, as follows;

Class InnerThread1 {private int countDown = 5; private Inner inner; private class Inner extends Thread {Inner (String name) {super (name); start ();} public void run () {try {while (true) {print (this); if (-- countDown = 0) return; sleep (10) ;}} catch (InterruptedException e) {print ("interrupted") ;}} public String toString () {return getName () + ":" + countDown ;}} public InnerThread1 (String name) {inner = new Inner (name );}}View Code method 3. Create a task class to implement the Runnable interface and submit the specific object to Executors [recommended]

Java. util. executors in the concurrent package can help us manage Thread objects and simplify concurrent programming. You can use the newCachedThreadPool static method in the Executors class to create a cache-able Thread pool and use it to execute related tasks;

package concurrency;import java.util.concurrent.*;public class CachedThreadPool {    public static void main(String[] args) {        ExecutorService exec = Executors.newCachedThreadPool();        for (int i = 0; i < 5; i++)            exec.execute(new LiftOff());        exec.shutdown();    }}

In the Executors class, in addition to creating a thread pool through newCachedThreadPool, you can also create other types of thread pools using the following methods:

NewFixedThreadPool: fixed-size Thread Pool

NewSingleThreadExecutor: Single-thread Thread Pool

NewScheduledThreadPool: scheduled and periodic tasks are executed.

Method 4: create a task class to implement the Callable interface and submit its specific object to Executors [recommended]

The class that implements the Callable interface is also a task class. The difference from implementing the Runnable interface is that this method can return values;

In the class that implements the Callable interface, the method that the thread executes is the call method (with a return value), rather than the run method;

In the main method, you can call the submit method of ExecutorService to return a Future object, through which you can obtain the return value of the thread running. Note that the result can be obtained only after the Future is completed, you can use the isDone method to check whether the Future is complete, or call the get method directly to obtain the result (blocking until the result is ready ).

package concurrency;import java.util.concurrent.*;import java.util.*;class TaskWithResult implements Callable<String> {    private int id;    public TaskWithResult(int id) {        this.id = id;    }    public String call() {        return "result of TaskWithResult " + id;    }}public class CallableDemo {    public static void main(String[] args) {        ExecutorService exec = Executors.newCachedThreadPool();        ArrayList<Future<String>> results = new ArrayList<Future<String>>();        for (int i = 0; i < 10; i++)            results.add(exec.submit(new TaskWithResult(i)));        for (Future<String> fs : results)            try {                System.out.println(fs.get());            } catch (InterruptedException e) {                System.out.println(e);                return;            } catch (ExecutionException e) {                System.out.println(e);            } finally {                exec.shutdown();            }    }} 
Summary

In fact, there are two ways to create a Thread: Implementing the Runnable interface and implementing the Callable interface. Thread is actually a class that implements the Runnable interface;

Daemon thread (background thread)

A daemon thread is a thread that provides a general service in the background when the program is running. This thread has a very low priority;

When all other threads end, all daemon threads in the process will be killed;

You can use the setDaemon (true) method to set the thread as a daemon before the thread starts. Note that the thread can only be set before it starts;

The thread created by the daemon thread is automatically set as the daemon thread;

The isDaemon method can be used to determine whether a thread is a daemon thread;

For example, the code for a daemon thread is as follows. When the main thread finishes running, all daemon threads are also terminated:

package concurrency;import java.util.concurrent.*;public class SimpleDaemons implements Runnable {    public void run() {        try {            while (true) {                TimeUnit.MILLISECONDS.sleep(100);                System.out.println(Thread.currentThread() + " " + this);            }        } catch (InterruptedException e) {            System.out.println("sleep() interrupted");        }    }    public static void main(String[] args) throws Exception {        for (int i = 0; i < 10; i++) {            Thread daemon = new Thread(new SimpleDaemons());            daemon.setDaemon(true); // Must call before start()            daemon.start();                    }        System.out.println("All daemons started");        TimeUnit.MILLISECONDS.sleep(175);    }}
Add a Thread. join Method

A thread (T1) can call the join method on other threads (T2). The result is that thread T1 is suspended and the execution of thread T2 is complete (T2.isAlive () = false ), then execute thread T1;

You can also add a timeout parameter to the join method to ensure that the join method can always return within the specified time;

The join method can be interrupted. If the T2.interrupt () method is called, The join method can return immediately after the interruption;

Code example:

package concurrency;class Sleeper extends Thread {    private int duration;    public Sleeper(String name, int sleepTime) {        super(name);        duration = sleepTime;        start();    }    public void run() {        try {            sleep(duration);        } catch (InterruptedException e) {            System.out.println(getName() + " was interrupted. "                    + "isInterrupted(): " + isInterrupted());            return;        }        System.out.println(getName() + " has awakened");    }}class Joiner extends Thread {    private Sleeper sleeper;    public Joiner(String name, Sleeper sleeper) {        super(name);        this.sleeper = sleeper;        start();    }    public void run() {        try {            sleeper.join();        } catch (InterruptedException e) {            System.out.println("Interrupted");        }        System.out.println(getName() + " join completed");    }}public class Joining {    public static void main(String[] args) {        Sleeper sleepy = new Sleeper("Sleepy", 1500), grumpy = new Sleeper(                "Grumpy", 1500);        Joiner dopey = new Joiner("Dopey", sleepy), doc = new Joiner("Doc",                grumpy);        grumpy.interrupt();                try {            sleepy.join();        } catch (InterruptedException e) {                        e.printStackTrace();        }        System.out.println("main thread continue until sleepy thread over");    }} 

In this example, we add the dopey and main threads to the sleepy thread and the doc thread to the grumpy thread. The result is as follows:

The grumpy thread is interrupted, and the join method returns immediately. Print Doc join completed. In the grumpy thread, the reason why isInterrupted () Prints false is that the flag is cleared during exception capture;

After the sleepy thread completes execution, the join method returns, continues executing the dopey thread and the unfinished part of the main thread, and prints "main thread continue until sleepy thread over" and "Dopey join completed ";

Capture thread exception

In the main method, try-catch cannot catch exceptions generated by other threads. In the following example, RuntimeException is not handled:

package concurrency;import java.util.concurrent.*;public class ExceptionThread implements Runnable {    public void run() {        throw new RuntimeException();    }    public static void main(String[] args) {        try {            ExecutorService exec = Executors.newCachedThreadPool();            exec.execute(new ExceptionThread());        } catch (RuntimeException ue) {            System.out.println("Exception has been handled!");        }    }}

Before JAVA SE5, you can use a thread group to capture exceptions. After JAVA SE5, you can use Executor to solve this problem;

You only need to write an exception handling class and implement Thread. uncaughtExceptionHandler interface. Then, when creating a thread, set the non-capturing exception processor of the thread to this type of instance and set it through the setUncaughtExceptionHandler method. The following code is used;

Package concurrency; import java. util. concurrent. *; class ExceptionThread2 implements Runnable {public void run () {Thread t = Thread. currentThread (); System. out. println ("run () by" + t); System. out. println ("eh =" + t. getUncaughtExceptionHandler (); throw new RuntimeException () ;}} class MyUncaughtExceptionHandler implements Thread. uncaughtExceptionHandler {public void uncaughtException (Thread t, Throwable e) {System. out. println ("caught" + e) ;}} class HandlerThreadFactory implements ThreadFactory {public Thread newThread (Runnable r) {System. out. println (this + "creating new Thread"); Thread t = new Thread (r); System. out. println ("created" + t); t. setUncaughtExceptionHandler (new MyUncaughtExceptionHandler (); System. out. println ("eh =" + t. getUncaughtExceptionHandler (); return t ;}} public class CaptureUncaughtException {public static void main (String [] args) {ExecutorService exec = Executors. newCachedThreadPool (new HandlerThreadFactory (); exec.exe cute (new ExceptionThread2 ());}}View Code

In addition to setting a dedicated uncaptured exception processor for each thread, you can also set the default uncaptured exception processor. When the system detects that a thread does not have a dedicated uncaptured exception processor, the default uncaptured exception processor is used;

package concurrency;import java.util.concurrent.*;public class SettingDefaultHandler {  public static void main(String[] args) {    Thread.setDefaultUncaughtExceptionHandler(new MyUncaughtExceptionHandler());    ExecutorService exec = Executors.newCachedThreadPool();    exec.execute(new ExceptionThread());  }} 

 

References: JAVA programming ideas-4

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.