This article has been published exclusively by guolin_blog, an official wechat account

There are several common ways to use threads

  • A:

  • Method 2:

  • Three:

Mode 1, mode 2, and mode 3 startup:

  public static void main(String[] args) throws ExecutionException, InterruptedException {
        / / way
        MyThread myThread = new MyThread();
        myThread.start();

        2 / / way
        MyRunnable myRunnable = new MyRunnable();
        new Thread(myRunnable).start();

        3 / / way
        MyCallable myCallable = new MyCallable();
        FutureTask<String> futureTask = new FutureTask<String>(myCallable) {
            @Override
            protected void done(a) {
                System.out.println("Way three before we start!");
                super.done();
                System.out.println("Mode three after execution!");
                try {
                    System.out.println("Done internal method 3 return result :" + get());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch(ExecutionException e) { e.printStackTrace(); }}};// Start the thread
        new Thread(futureTask).start();

        System.out.println("Obtain method three return result :" + futureTask.get());
}
Copy the code

Running results:The differences between the three ways:

  • extend ThreadI need to override it manuallyrunmethods
  • implements RunnableYou need to put the currentrunnableObject toThreadIn the
  • implements Callable<*>Access tothread, and cannot be passed directly to thread to startFutureTaskTo match, and can passFutureTask.get()Get the implementationImplements Callable < * >thecallThe return value of.

The difference between thread.start () and thread.run ()

Here’s another piece of code:

  • start:
    Client4Thread client4Thread = new Client4Thread();
    client4Thread.start();
    Copy the code

    Running results:

    thread:Thread-0
    Copy the code
  • run:
    Client4Thread client4Thread = new Client4Thread();
    client4Thread.run();
    Copy the code

    Running results:

    thread:main
    Copy the code

Conclusion: Calling thread.run () is equivalent to an ordinary class calling a run method without opening child threads

Equivalent to this:

public static class User {
  public void run(a) {
         System.out.println("User.run"+ Thread.currentThread().getName()); }}Copy the code

Client4thread.run () is equivalent to user.run ()!

Client4Thread client4Thread = new Client4Thread();
// client4Thread.start();

// It has the same effect
client4Thread.run();
//
//
new User().run();
Copy the code

Thread.join() Thread serialization

Let’s take a look at the usage scenario:

Now we have three threads running at the same time. Let’s see what happens:

As you can see, the order of execution is different each time..

If you want it to be synchronized, you can do this:

Conclusion: The purpose of a JOIN is to join threadsserialization, it should be noted that,join()Be sure to open it on site (start()),

Thread.interrupt () Interrupts a Thread

Run code:The running results are as follows:As you can see, although an interrupt signal is sent to the child thread, the thread does not execute the terminal, but lives on.

If you want a Thread to interrupt, simply check for isInterrupted() in Thread

For example:The running results are as follows: The small hole:If you need to be in! isInterrupted()For example:You can’t do that becauseThread.sleepThe interrupt signal is captured and changed tofalse

And it ended up like this

Eventually, an interrupt exception was caught, but Thread.sleep() arbitrarily changed it.. Simply change the status again when you catch InterruptedException:

For example:Of course it’s not justextend ThreadThis way of writing interrupts the thread,implements RunnableIt is also possible to interrupt the thread, for example:

The effect is the same, I will not repeat the show..

Thread data sharing synchronized

Let’s start with a simple example:

There are now2Two threads need to be paired simultaneouslycount ++, for example:The result is:You can see that it’s different every time you run it, right?

Why is that?

Because the loop is adding 1000 * 100 times, when two threads are running at the same time, two counts are executed at the same time, so the numbers are always wrong.

Just synchronize it (add a lock), for example:

Common lock writing method:

  • Lock the class of a class:

    private static final Object object = new Object();
    
    public static void addCount(a) {
        for (int i = 0; i < countLength; i++) {
            synchronized(object) { count++; }}}Copy the code
  • Lock this of the current object

    public synchronized void addCount2(a) {... }Copy the code
  • Lock the class of the specified object:

    public static void addCount(a) {
      for (int i = 0; i < countLength; i++) {
               synchronized(Client2.class) { count++; }}}Copy the code

Thread Isolation (ThreadLocal)

What is thread isolation? Let’s look at the code:But first, the results:As you can see, the effect of each run is not the same

This is because at start, the thread is just ready to tell the JVM that I’m ready to execute. The JVM calls the actual execution

Look at the problem in terms of the last result:

ThreadName:Thread-1	threadIndex:1	count:2
ThreadName:Thread-4	threadIndex:4	count:11
ThreadName:Thread-3	threadIndex:3	count:7
ThreadName:Thread-2	threadIndex:2	count:4
ThreadName:Thread-0	threadIndex:0	count:2
Copy the code

Let’s look at the code first:

In the main method, 5 threads are opened and subscripts are passed in, and MyThreadLocal is added to the table below

Demand analysis:

Since we’re talking about thread isolation, the desired effect should be that if 5 is now coming in, then pass

count+=threadIndex;
Copy the code

The result should be 6, instead of counting the results of other threads to the current thread

ThreadLocal = ThreadLocal = ThreadLocal = ThreadLocal

One was added at startupThread.join()Cause threads to execute sequentially..

Look directly at the effect:

As you can see, thread isolation is now implemented

If you read the Handler source code, you’ll also see that it uses ThreadLocal internally for thread isolation

Thread isolation, however, isolates loppers to ensure that a thread has only one Looper

Glance athandlerThe code:

Use of notify(),notifyAll(), and wait()

Tips: Notify () notifyAll() and wait are properties of Object(), so each class can be called

Here’s how they differ:

  • WaitAndNotifyBean:

Wait for a refresh via 'changeName()' by calling 'waitName()'Copy the code
  • MyThread:

  • Use:

Take a look at the results:

notify notifyAll

Notify and notifyAll wake up a thread after a wait

Next, increase the dose!

notify notifyAll

As you can see, the effect is very obvious!

Multiple threads wait case

  • notify, only one will refreshawit, the other threads continue to wait
  • notifyAll, will refresh all wait!

NotifyAll notify() and wait() should be placed inside locks.

According to the lock

ReentrantLock

What is reentrant?

int count = 0;
public synchronized void test(a) {
     count++;
     if (count <= 10) { test(); }}Copy the code

Take synchronized for example. Based on current knowledge,synchronized is bound to be locked recursively because the first time test() is executed, the lock is locked again before it is released

But synchronized turns out to be fine, because synchronized is reentrant, which means that if the same instance is used, it can be re-entered

The same goes for ReentrantLock

Take a look at ReentrantLock in action:The result was the same:The important thing to note here is that when using implicit locks, it must be placed intry { ... } finally { .. }Block of code

This is done because even if an exception is thrown, the lock will be released and no deadlock will occur

Sample specification:

lock.lock();
try{
    count++;
} finally {
    lock.unlock();
}
Copy the code

Read-write lock (ReentrantReadWriteLock)

To stand out as ReentrantReadWriteLock, you need a comparison, and synchronized!

Open 3 writer threads and 30 reader threads to simulate the read operation in real development

See how synchronized and read-write locks work in action!

Here’s the code idea:

  • StudentImpl

  • getThread:
  • setThread:

Run:

Synchronized effect and read/write lock comparison:

synchronized Read-write lock

As can be seen, the effect is very obvious, from the change can also be seen, if you want to do a lot of read and write operations, using read and write lock efficiency will be greatly improved!

Extracurricular knowledge volatile!

Volatile is not the knowledge of Thread, but let’s talk about keywords.

Or a piece of code that makes the difference:

Without volatile:Effect:

As you can see, novolatileKey words,isRunEven if it is changed, there is no response in the thread.

Now let’s look at addingvolatileKey words:Effect:The results are obvious, once markedvolatile isRunA variable is notified directly whenever it changesJVMTo change the current state!!

The complete code

Original is not easy, your praise is the biggest support for me!