Processes and threads

  • process
    • An instance of a program (usually only one instance of a program)
  • thread
    • The smallest executable unit
    • A process can have multiple threads (a process must have one thread)

A simple explanation of processes and threads

How threads are created

  1. Thread class inheritance
    • If run() is called directly, it suspends the current method and waits for run() to complete, just like normal method calls
    class ThreadDemo extends Thread {
        // No parameter constructor
        ThreadDemo(){ }
        
        public void run(a){
            // Custom code}}public statin void main(String[] args){
        
        // Call the no-argument constructor to create the thread object
        ThreadDemo td = new ThreadDemo();
        
        /* There is a difference between starting a new thread and calling the run() method. The run() method pushes the current thread, waits for the run() method to complete, and then returns to the current method */
        td.start();
    }
    Copy the code
  2. Implement the Runnable interface
    • All three are essentially implementations of Runnable
    class RunDemo implements Runnable {
        RunDemo(){}
        
        // Implement the run() method of the interface
        public void run(a){
            // Custom code}}public static void main(String[] args){
        
        Runnable runDemo = new RunDemo();
        
        // Call the parameter constructor of Thread and pass in an implementation of the Thread interface to create and start the Thread
        new Thread(runDemo).start();
    }
Copy the code
  1. Implement Callable interface
    • Callable needs to be wrapped as a Future

    • The Future needs to be wrapped as FutureTask

    • FutureTask actually implements the RunnableFuture interface

    • The RunnableFuture interface is a combination of Runnable and Future

    • So, a Callable is essentially a Runnable

    • How a thread is created that can return values

    3.1 Callable + Future

        public class CallAndFuture implements Callable{
    
     private String name;
    
     public CallAndFuture(String name ){
         this.name = name;
     }
    
    
     public String call(a){
    
    
         return "11111133333" + this.name;
     }
    
    
     public static void main (String[] args) throws ExecutionException, InterruptedException {
         /* code */
    
         CallAndFuture callOne = new CallAndFuture("The one");
         CallAndFuture callTwo = new CallAndFuture("The results of two");
         CallAndFuture callThree = new CallAndFuture("The three");
    
         ExecutorService es = Executors.newFixedThreadPool(3);
    
         Future futureOne = es.submit(callOne);
    
         System.out.println(futureOne.get());
    
         Future futureTwo = es.submit(callTwo);
    
         System.out.println(futureTwo.get());
    
         Future futureThree = es.submit(callThree);
    
         System.out.println(futureThree.get());
    
         es.shutdown();
     }
    
    Copy the code

    3.2 + FutureTask Callable

  • The get() method blocks the main thread, usually using get(long timeout, TimeUnit unit) with a timeout.

  • Generally, the thread execution results are obtained after other tasks are completed. If subsequent results depend on the results of thread execution, you can block the wait (but why?).

Thread state

  1. NEW
  2. Run (RUNNABLE)
    • ready
    • In the operation of the
  3. WAITING.
    • Waiting for action (notification or interrupt) from another thread
  4. They are BLOCKED.
    • Due to the lock block
  5. Timeout waiting (TIMED_WAITING)
    • Wait with an end time
    • After the specified time, the queue automatically returns to the ready state
    • The sleep() method raises this state
  6. Death (TERMINATED)
    • completed

The final execution method of a thread

  • native void start0()
  • start0()Methods are composed of static methodsstatic native void registerNatives()Prepare for initialization
  • So, in essence, Java does not start threads. Instead, the underlying C++ implementation method start0 does

Common methods of threading

  1. wait
    • Calling this method to put the thread into the wait state releases the lock
  2. join
    • Thread enforcement, commonly known as queue jumping. Whoever called will be blocked.
  3. notify
    • Wakes up a thread in the wait queue to compete for CPU
  4. notifyAll
    • Wake up all threads in the wait queue to compete for CPU
  5. Stop (not recommended)
  6. Destroy (not recommended)
  7. yield
    • Thread comity. Exit the CPU and recompete with other threads.
    • May again compete to CPU, completely depends on CPU mood.
  8. sleep
    • Calling this method blocks the thread and does not release the lock

Synchronization mechanism for threads

  • synchronized
    • Methods can be locked
      • public synchronized void test(){}
    • Blocks of code can be locked
      • synchronized(obj){}
  • Lockinterface
    • Blocks of code can be locked
    • Already locked
        ReentrantLock lock = new ReentrantLock();
        try{
            / / lock
            lock.lock();
        }finally{
            / / unlock
            lock.unlock();
        }
    Copy the code
    • LockSupport
    class FIFOMutex {
    
        private final AtomicBoolean locked = new AtomicBoolean(false);
        private final Queue<Thread> waiters = new ConcurrentLinkedQueue<Thread>();
     
        public void lock(a) {
              boolean wasInterrupted = false;
              Thread current = Thread.currentThread();
              waiters.add(current);
     
          // Block while not first in queue or cannot acquire lock
              while(waiters.peek() ! = current || ! locked.compareAndSet(false.true)) {
                LockSupport.park(this);
                if (Thread.interrupted()) // ignore interrupts while waiting
                  wasInterrupted = true;
              }
     
              waiters.remove();
          if (wasInterrupted)          // reassert interrupt status on exit
                current.interrupt();
        }
     
        public void unlock(a) {
          locked.set(false); LockSupport.unpark(waiters.peek()); }}}Copy the code
    • ReentrantReadWriteLock Reentrant read/write lock
    public class ReadWriteLockDemo {
    
        public static void main(String[] args) {
            Note note = new Note();
    
            for (int i = 0; i < 100; i++) {
                if( i%10= =0) {new Thread(new TakeNote(note)).start();
                } else {
                    new Thread(newViewNote(note)).start(); }}}}class TakeNote implements Runnable{
    
        private Note note = null;
    
        public TakeNote(Note n){
            this.note = n;
        }
    
        @Override
        public void run(a) {
            try {
    
                this.note.add("= = = =" + Thread.currentThread().getName());
    
            } catch(InterruptedException e) { e.printStackTrace(); }}}class ViewNote implements Runnable {
    
        private Note note = null;
    
    
        public ViewNote(Note note){
            this.note = note;
        }
    
        @Override
        public void run(a) {
    
            try {
                this.note.get();
            } catch(InterruptedException e) { e.printStackTrace(); }}}class Note{
    
        private ArrayList<String> al = new ArrayList<String>();
    
        private ReentrantReadWriteLock rtRw = new ReentrantReadWriteLock();
        private Lock readLock = rtRw.readLock();
        private Lock writeLock = rtRw.writeLock();
    
        public void add(String note) throws InterruptedException {
            writeLock.lock();
            System.out.println("===**** taking notes taking notes ===" + Thread.currentThread().getName());
            al.add(note);
            Thread.sleep(5000);
            System.out.println("===**** finish notes ===" + Thread.currentThread().getName());
            writeLock.unlock();
        }
    
        public String get(a) throws InterruptedException {
            // Read lock can be entered multiple times
            readLock.lock();
            System.out.println("=== viewing notes ===" + Thread.currentThread().getName());
            if(al.size() == 0) {readLock.unlock(); return ""; } String re = al.get(al.size()-1);
            Thread.sleep(2000);
            System.out.println("=== Look up your notes ===" + Thread.currentThread().getName());
            readLock.unlock();
            returnre; }}Copy the code
    • StampedLockThe seal lock
    class Point {
        private double x, y;
        private final StampedLock sl = new StampedLock();

        void move(double deltaX, double deltaY) { // an exclusively locked method
          long stamp = sl.writeLock();
          try {
            x += deltaX;
            y += deltaY;
          } finally{ sl.unlockWrite(stamp); }}double distanceFromOrigin(a) { // A read-only method
          // Get optimistic read locks
          long stamp = sl.tryOptimisticRead();
          double currentX = x, currentY = y;
          if(! sl.validate(stamp)) { stamp = sl.readLock();try {
               currentX = x;
               currentY = y;
             } finally{ sl.unlockRead(stamp); }}return Math.sqrt(currentX * currentX + currentY * currentY);
        }

        void moveIfAtOrigin(double newX, double newY) { // upgrade
          // Could instead start with optimistic, not read mode
          long stamp = sl.readLock();
          try {
            while (x == 0.0 && y == 0.0) {
              // Try converting to write lock
              long ws = sl.tryConvertToWriteLock(stamp);
              if(ws ! =0L) {
                stamp = ws;
                x = newX;
                y = newY;
                break;
              }
              else{ sl.unlockRead(stamp); stamp = sl.writeLock(); }}}finally{ sl.unlock(stamp); }}}}Copy the code

Priority of the thread

  • A higher priority is more likely to be executed by the CPU than a lower priority
  • The value range of the priority is a positive integer[1-10]
  • SetPriority () sets the priority
  • Some constants of the priority
    • Thread.MIN_PRIORITY (1)
    • Thread.NORM_PRIORITY (5)
    • Thread.MAX_PRIORITY (10)

Daemon threads

  • Normal threads are user threads
  • setDaemon(true)Start daemon thread
  • The virtual machine must wait for all user threads to complete, but not for the daemon thread to complete
  • Common daemon threads
    • GC garbage collection thread

Thread communication

Producer-consumer model

Lock the nature

  • What exactly does a lock lock? (Only two)
    • Instance object (there can be more than one)
    • Class object (there is only one Class object for a Class)

Some problems with thread concurrency

False awaken

  • Wakes up multiple related threads, but does not actually meet the execution condition
  • Use of wait and notifyAll
    • Wait is placed in a while loop to avoid the problem of false awakenings

A deadlock

  • Four necessary conditions for deadlocks
    • The mutex
    • Hold and wait
    • Resources must not be forcibly taken away
    • Circular waiting (the required resource is in someone else’s hands)