Java multi-threading Thread

Multithreading: refers to the production of more than one thread of this program (a process) is running

  • Parallel and Concurrent:
    • Parallel: a plurality of instances cpu or simultaneously performed for a plurality of machines processing logic is true simultaneously.
    • Concurrency: By cpu scheduling algorithms, allowing users to perform simultaneously looks, in fact, from the operational level cpu is not true at the same time. Concurrent often have common resources in the scene, so often a bottleneck for this common resource, we will use the TPS or QPS to reflect the processing power of the system.

Concurrent and Parallel
  • Security Thread: often used to describe a piece of code. Refers to the circumstances concurrent multithreading this code after use, the thread scheduling order does not affect any of the results. This time using multiple threads, we just need to focus on system memory, cpu is not enough can be. In turn, thread safe means of threads on the scheduling order will affect the final result, as the transaction without transfer of code:
void transferMoney(User from, User to, float amount){
  to.setMoney(to.getBalance() + amount);
  from.setMoney(from.getBalance() - amount);
} 

Synchronization: Java synchronization refers to artificially control and scheduling, to ensure that multi-threaded access to shared resources to be thread-safe, to ensure accurate results. As the above code simply adding @synchronizedkeywords. To ensure accurate results while improving performance, is an excellent program. Thread safety a higher priority than performance.

State of the thread

 

 

Threads may encounter blocked (Blocked) in the case of the process Running

  1. Call join () and sleep () method, sleep () end time or interrupted, join () interrupt, IO will return to complete the Runnable state, waiting for the JVM scheduling.
  2. Call wait (), the thread is waiting for the pool (wait blocked pool), until the notify () / notifyAll (), the thread wakes up locked into the pool (lock blocked pool), the thread synchronization lock is released back to runnable (Runnable)
  3. Plus thread synchronization lock on the Running state (Synchronized) it into (lock blocked pool), synchronization lock is released into the run state (Runnable).

Further, in the state of the thread is in the runnable thread is scheduled, the scheduling sequence at this time is not constant. yield method of the Thread class can make a thread running state into runnable.

 

Each object has a method (mechanism)

 

synchronized, wait, notify any objects have a synchronization tool. Let's first understand them

 


 

 


They are used in manual synchronization thread scheduling tool. Stresses its nature, we must first define the concept of monitor, Java each object has a monitor, to monitor the concurrent code reentrant. When the non-multithreaded coding monitor does not function, whereas if the range synchronized in the monitor to play a role.

 

wait / notify must exist in the synchronized block. And this is the same three keywords for a monitor (monitor an object). This means that after wait, other threads can enter the synchronized block is executed.

 

When a code is not held monitor usage right (in the state of FIG. 5, i.e. from the sync blocks) to wait or notify, throws java.lang.IllegalMonitorStateException. Also included in the synchronized block to call another object wait / notify, because different object's monitor, the same will be thrown.

 

Repeat usage:

 

  • synchronized alone:
    • Block: as follows, in multi-threaded environment, the method of acquiring a synchronized block monitor lock example, if the same examples, only one thread can perform the block content
public class Thread1 implements Runnable {
   Object lock;
   public void run() {  
       synchronized(lock){
         ..do something
       }
   }
}

直接用于方法: 相当于上面代码中用lock来锁定的效果,实际获取的是Thread1类的monitor。更进一步,如果修饰的是static方法,则锁定该类所有实例。

public class Thread1 implements Runnable {
   public synchronized void run() {  
        ..do something
   }
}

synchronized, wait, notify结合:典型场景生产者消费者问题

复制代码
/**
   * 生产者生产出来的产品交给店员
   */
  public synchronized void produce()
  {
      if(this.product >= MAX_PRODUCT)
      {
          try
          {
              wait();  
              System.out.println("产品已满,请稍候再生产");
          }
          catch(InterruptedException e)
          {
              e.printStackTrace();
          }
          return;
      }

      this.product++;
      System.out.println("生产者生产第" + this.product + "个产品.");
      notifyAll();   //通知等待区的消费者可以取出产品了
  }

  /**
   * 消费者从店员取产品
   */
  public synchronized void consume()
  {
      if(this.product <= MIN_PRODUCT)
      {
          try 
          {
              wait(); 
              System.out.println("缺货,稍候再取");
          } 
          catch (InterruptedException e) 
          {
              e.printStackTrace();
          }
          return;
      }

      System.out.println("消费者取走了第" + this.product + "个产品.");
      this.product--;
      notifyAll();   //通知等待去的生产者可以生产产品了
  }
复制代码

 

 

 

volatile

 

多线程的内存模型:main memory(主存)、working memory(线程栈),在处理数据时,线程会把值从主存load到本地栈,完成操作后再save回去(volatile关键词的作用:每次针对该变量的操作都激发一次load and save)。

 

 


 

 

针对多线程使用的变量如果不是volatile或者final修饰的,很有可能产生不可预知的结果(另一个线程修改了这个值,但是之后在某线程看到的是修改之前的值)。其实道理上讲同一实例的同一属性本身只有一个副本。但是多线程是会缓存值的,本质上,volatile就是不去缓存,直接取值。在线程安全的情况下加volatile会牺牲性能。

 

基本线程类

基本线程类指的是Thread类,Runnable接口,Callable接口
Thread 类实现了Runnable接口,启动一个线程的方法:

 MyThread my = new MyThread();
  my.start();

Thread类相关方法:

复制代码
//当前线程可转让cpu控制权,让别的就绪状态线程运行(切换)
public static Thread.yield() 
//暂停一段时间
public static Thread.sleep()  
//在一个线程中调用other.join(),将等待other执行完后才继续本线程。    
public join()
//后两个函数皆可以被打断
public interrupte()
复制代码

关于中断:它并不像stop方法那样会中断一个正在运行的线程。线程会不时地检测中断标识位,以判断线程是否应该被中断(中断标识值是否为true)。终端只会影响到wait状态、sleep状态和join状态。被打断的线程会抛出InterruptedException。
Thread.interrupted()检查当前线程是否发生中断,返回boolean
synchronized在获锁的过程中是不能被中断的。

中断是一个状态!interrupt()方法只是将这个状态置为true而已。所以说正常运行的程序不去检测状态,就不会终止,而wait等阻塞方法会去检查并抛出异常。如果在正常运行的程序中添加while(!Thread.interrupted()) ,则同样可以在中断后离开代码体

Thread类最佳实践
写的时候最好要设置线程名称 Thread.name,并设置线程组 ThreadGroup,目的是方便管理。在出现问题的时候,打印线程栈 (jstack -pid) 一眼就可以看出是哪个线程出的问题,这个线程是干什么的。

如何获取线程中的异常


不能用try,catch来获取线程中的异常

Runnable

与Thread类似

Callable

future模式:并发模式的一种,可以有两种形式,即无阻塞和阻塞,分别是isDone和get。其中Future对象用来存放该线程的返回值以及状态

ExecutorService e = Executors.newFixedThreadPool(3);
 //submit方法有多重参数版本,及支持callable也能够支持runnable接口类型.
Future future = e.submit(new myCallable());
future.isDone() //return true,false 无阻塞
future.get() // return 返回值,阻塞直到该线程运行结束

 

转载于:https://www.cnblogs.com/lucky1024/p/11040444.html

Guess you like

Origin blog.csdn.net/weixin_34259559/article/details/93249912