Multithreading related notes

Preface

About class and table locks, online piles, this I will not say more.

Because the content is not substantial, to not advertised.

 

Article: On Java in the lock: Synchronized, re-entry lock , write lock  - Jane books

https://www.jianshu.com/p/21e095b71373

Thread six states (Source Thread class has enum state)

1.  Initial (NEW) : create a new thread object, but has not been called start () method.
2.  Run (RUNNABLE) : the Java thread will be ready (ready) and running (running) two states generally referred to as "run."
After the thread object is created, other threads (such as main thread) calls the start () method of the object. The thread state is located runnable threads in the pool, waiting to be selected thread scheduling, acquiring the right to use the CPU, this time in a ready state (ready). Ready state after obtaining thread CPU time slice becomes operational status (running).
3. blocked (BLOCKED) : means the thread is blocked in the lock.
4. wait for (the WAITING) : This state is entered threads need to wait for other threads to make some specific action (notification or interrupt).
The time-out period (TIMED_WAITING) : This state is different WAITING, it can return itself after a specified time.

6.  termination (TERMINATED) : the thread has finished.

Easy to understand, you can refer to the diagram, although not one correspondence with the source state.

 

Effect of Spot function of the state

  1. 1. yield () method, translated thread concessions. After the name suggests, that when a thread using this method, it will own CPU execution time to let out, let yourself or other threads running, is to pay attention to their own or other threads running, not simply to give other threads .                                                        For example: a group of friends in the queue on the bus, turn to Yield when he suddenly said: I do not want to go up, to let everyone on the bus race. Then everyone rushed on a bus, there may be other people get on the bus, there may be Yield to on the bus.
  2. Thread.sleep (long millis), the current thread must call this method, the current thread into the TIMED_WAITING state, but does not release the object lock, automatic wake up after millis thread into the ready state. Role: The best way to give the opportunity to perform other threads.
  3. t.join () / t.join (long millis), thread the current method call join other thread t, the current thread into the WAITING / TIMED_WAITING state will not release the current thread already holds the object lock. Thread t finished or millis time to, the current thread into the ready state.
  4. obj.wait (), the current thread calls the object's wait () method, the current thread releases the object lock, into the waiting queue. Rely notify () / notifyAll () Wake or wait (long timeout) timeout time to automatically wake.
  5. obj.notify () wake up a single thread waiting on this object's monitor, the choice is arbitrary. notifyAll () wakes up all threads waiting on this object's monitor.

 

1.ReenTranLock和synchronized

Usage scenarios: In general, if not complicated proposed business use synchronized, because synchroized automatic optimization of the bottom, and it supports automatic abnormal release the lock, if an exception occurs not write reentrant lock thread releases the lock will be blocked in the code; but if the business complex (eg multi-threaded according to the order one would have to stop for a while, one would then wake up this troublesome business), using only synchronized to the code size is not good grasp, reentrant lock the wording more inclined to process-oriented, for the better control logic; reentrant lock course this system there are many other functions, by definition it is reentrant lock, this is a digression.

2.synchronized (Object)

Whether this object is based on what determines it? General on means-plus-synchronized objects defaults to this, it refers to the class. If so locked in this class is multi-threaded programming in general on a shared variable that can not go wrong, but the performance may still not optimal, because the lock has its scope, if the whole object is locked, then the same use a synchronized (the object) within the same code block in time only one thread execution right to get the lock, the lock is locked other threads of the object blocks will only wait a.

For example, is ConcurrentHashMap, different from the thread-safe deprecated HashTable (it just add synchronized field, compare performance on simple violence), concurrentHashMap locked when not directly initialize the array, but the use of CompareAndSwap CAS operation, and when added to the array of list node node, the synchronized (the current node node); scope merely the synchronized lock current node, so what benefits are achieved, see Figure:

1. A simple force applied to the object lock operation in the data node is added, so that the entire array HashMap have been locked, the performance is not good

2. The synchronized (the current node node), then bit into the hashMap other nodes when data array, it will not be blocked. Because of this action and write dirty data does not occur, so the implementation of a more reasonable and good performance.

 

About ThreadPoolExecutor

ThreadPoolExecutor threadPool = new ThreadPoolExecutor(1,1,0,TimeUnit.SECONDS,
                       new LinkedBlockingQueue<Runnable>(100),new ThreadPoolExecutor.DiscardOldestPolicy());

Emphasize again, ThreadPoolExecutor core of four points:

1, when there are tasks submitted, create a core thread to perform the task (even if the core thread is idle);

2, when the core reaches the number of threads corePoolSize, are submitted into the queue subsequent BlockingQueue;

3, when BlockingQueue full (offer fails), it will create a temporary thread (the thread temporarily idle more than a certain time, will be destroyed);

4, when the total number of threads reaches maximumPoolSize, follow-up submitted tasks are rejected RejectedExecutionHandler
 

The use of locks

/**
 * @ClassName FirstController
 * @Description 测试
 * gain: 这个案例故意写得不规范,总结一些问题,
 * 1.调用Condition.await()/singnal() 的时候,当前线程需要获得锁
 * 2.await()调用后,当前线程释放锁。但死锁的形成原因一般为: 双方都调用await()后等待,没有线程跑下去。
 * 3.业务复杂一般倾向用ReentrantLock,但synchronized(String)使用也很简易,、
 * 4.String.intern()方法会从字符池拿变量,所以"1".equals(new String("1").intern())结果为true
 * 5.tryLock(); 多线程里防止重复执行的内容,例如重复提交等,一般在if()内使用
    //根据尝试获取锁的值来判断具体执行的代码
    if(lock.tryLock(long time , TimeUnit unit)) {
    try{
    //处理任务
    }catch(Exception ex){

    }finally{
    //当获取锁成功时最后一定要记住finally去关闭锁
    lock.unlock();   //释放锁
    }
    }else {
    //else时为未获取锁,则无需去关闭锁
    //如果不能获取锁,则直接做其他事情
    }
 *
 * @Author lkun
 **/
@ApiIgnore
@RestController
public class FirstController {

    int bSize = 500;

    private final static Logger logger = LoggerFactory.getLogger(FirstController.class);

    private ExecutorService threadPool;

    private Lock lock = new ReentrantLock();
    private final Condition firstB = lock.newCondition();

    final AtomicInteger atoInt = new AtomicInteger();
    {
        //threadPool = Executors.newSingleThreadExecutor();
        threadPool = new ThreadPoolExecutor(2, 50, 100,
                TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(300),new ThreadPoolExecutor.CallerRunsPolicy());
    }

    @Autowired
    IrisDataService irisDataService;

    @Autowired
    JdbcTemplate jdbcTemplate;

    @Autowired
    IrisDataRepository irisDataRepository;

    @RequestMapping(value = "/helloWorld",method = RequestMethod.GET)
    public String helloWorld() throws Exception {
        atoInt.set(bSize);

        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 1000; i++) {
                    final int num = i;
                    lock.lock();
                    try {
                        if (atoInt.get() > 0) {
                            firstB.await();
                        }
                        threadPool.execute(new Runnable() {
                            @Override
                            public void run()  {
                                try {
                                    Thread.sleep(2000);
                                    System.out.println("run thread A: " + num);
                                }catch(Exception e) {
                                    logger.error("异常A");
                                }

                            }
                        });
                    } catch (Exception e) {
                        logger.error("error thread:" + e.getMessage(), e);
                    }finally {
                        lock.unlock();
                    }
                }
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                for(int i = 0; i < bSize; i++) {
                    final int num = i;
                    threadPool.execute(new Runnable(){
                        @Override
                        public void run(){
                            try {
                                Thread.sleep(1000);
                                System.out.println("run thread B: " + num);
                                if(atoInt.addAndGet(-1) <= 0) {
                                    //sinal()前提是需要获取锁,但这里想让并发处理尽可能高性能,所以建议把lock()住的代码块尽量简短
                                    lock.lock();
                                    firstB.signal();
                                    lock.unlock();
                                };
                            }catch(Exception e){
                                logger.error("error thread:" + e.getMessage(),e);
                            }
                        }
                    });
                }
            }
        }).start();
        for(int i = 0 ; i < 1000; i++) {
            System.out.println("main Thread run" + i);
        }
        return "true";
    }

    @RequestMapping(value = "/testMethod",method = RequestMethod.GET)
    public String testMethod() {
        new Thread(new Runnable(){
            @Override
            public void run() {
                synA();
            }
        }).start();
        new Thread(new Runnable(){
            @Override
            public void run() {
                synB();
            }
        }).start();
        return "test success11ger";
    }

    private void synA() {
        synchronized("1") {
            for(int i = 0 ; i < 1000; i++) {
                try {
                    Thread.sleep(600);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("A run :" + i);
            }
        }
    }

    private void synB() {
        synchronized(new String("1").intern()) {
            for(int i = 0 ; i < 1000; i++) {
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("B run :" + i);
            }
        }
    }
}


2.CountDownLatch (such concurrent for statistical results)

// This example has a problem, too many threads to create, not realistic

public ResultMes republishByDatabase(final String sn) throws Exception {
        logger.info("开始重发人员数据,sn=" + sn);
        //获取流程成功下发人员记录
        List mapList = jdbcTemplate.queryForList("select t2.id_number,t2.status from iotmgr_device t1,dr_authorized_detail t2  " +
                "where t1.device_code = t2.device_code and t1.brand = 'IK' and t1.parameter_id = ? and t1.delete_type = '0' and t2.status in('1','2')",new Object[]{sn});

        int leng = mapList.size();
        final StringBuffer logBuilder = new StringBuffer();
        final AtomicInteger failCounter = new AtomicInteger();
        Thread[] threads = new Thread[leng];
        final CountDownLatch latch = new CountDownLatch(leng);
        final Lock lock = new ReentrantLock();

        //全部下发后,统计下发结果
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    latch.await();
                    logger.info("重发人员数据结束,sn=" + sn);
                    if(logBuilder.length() > 0) {
                        logger.error(logBuilder.toString());
                        logger.error("重发失败数目=" + failCounter.get());
                    }else {
                        logger.info("重发人员数据全部成功!");
                    }
                }catch(Exception e) {
                    logger.error("重发countDownLatch异常" + e.getMessage());
                }
            }
        }).start();

        for(int i = 0; i < leng; i++) {
            final Map map = (Map)mapList.get(i);
            threads[i] = new Thread(new Runnable() {
                @Override
                public void run() {
                    ResultMes resMessage = null;
                    String idNumber = null;
                    Integer sendCardNumber = 1;  //是否下发卡号
                    try {
                        lock.lock();
                        String status = (String)map.get("status");  //授权状态
                        idNumber = (String)map.get("id_number"); //身份证
                        if("1".equals(status)) { //正常使用
                            sendCardNumber = 1;
                        }else if("2".equals(status)) { //挂失卡
                            sendCardNumber = 0;
                        }else if("3".equals(status)) {  //失效
                            return;
                        }
                        resMessage = addIrisBusiness(sn,idNumber,0,sendCardNumber); //下发人员数据
                    }catch(Exception e) {
                        failCounter.incrementAndGet();
                        latch.countDown();
                        lock.unlock();
                        //防止数据不完整会导致异常中断操作。这里仅对异常捕捉打印日志
                        logBuilder.append("下发失败idNumber=" + idNumber + e.getMessage() + "\r\n");
                        return;
                    }
                    if(!resMessage.isSuccess()) {
                        failCounter.incrementAndGet();
                        logBuilder.append("下发失败idNumber=" + idNumber + resMessage.getMessage() + "\r\n");
                    }
                    latch.countDown();
                    lock.unlock();
                }
            });
            threads[i].start();
        }

        return ResultMes.buildSuccess();
    }

 

Published 21 original articles · won praise 9 · views 30000 +

Guess you like

Origin blog.csdn.net/a5552157/article/details/85474533