通过新的tryLock方法

时间:2017-10-29 19:31:51

标签: java java-8 thread-safety executorservice reentrantlock

我正在 ReentrantLock 类中浏览 lockInterruptibly 方法的java doc说明。 我的目的是看看等待获取锁的线程是否正在被中断,可能是我做错了。我知道有一种在Thread上调用中断的明确方法,而我正在使用的executorService可能已经在它的API下包含了这个概念。

使用锁定方法也可以看到此行为

我的目的是详细了解这个概念

import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;

public class LockInterruptibly extends Thread {

    static ExecutorService es = Executors.newFixedThreadPool(5);
    static Lock lock1 = new java.util.concurrent.locks.ReentrantLock();

    public void methodA() {
        if (lock1.tryLock()) {

            try {
                lock1.lockInterruptibly();
                System.out.println("lock acquired by " + this.getName() + "  of method A");
                Thread.sleep(5000);

            } catch (InterruptedException e) {

                System.out.println("this thread " + this.getName() + " was interrupted");
                e.printStackTrace();
            }
        } else {
            System.out.println(this.getName() + "failed to acquire lock");
        }
    }

    public void methodB() {
        for (int i = 0; i < 5; i++) {
            System.out.println("Printed by " + this.getName() + " - " + i);
        }
        lock1.unlock();
        System.out.println(this.getName() + " is exiting at time " + new Date(System.currentTimeMillis()));
    }

    @Override
    public void run() {
        methodA();
        methodB();
    }

    public static void main(String args[]) {
        System.out.println(new Date(System.currentTimeMillis()));
        for (int i = 0; i < 10; i++) {
            Runnable r = new Thread(new LockInterruptibly());
            es.submit(r);
        }
        System.out.println(new Date(System.currentTimeMillis()));
    }
}

现在看下面的控制台输出: console logs showing the relative order, when each thread acquires lock and releases it

我的问题是: 1)为什么这种交错行为? 为什么超过1个线程能够获取锁(至少根据控制台输出),它几乎就像获取锁的递归行为。或者仅仅因为控制台输出与实际发生的事情不同步? 2)它与执行者处理耗时线程的方式有关并且是正常行为吗?

1 个答案:

答案 0 :(得分:0)

感谢您的评论!我正在阅读关于新的Lock api以及如何在实际“获取”它之前尝试锁定。所以我想编写线程是否真的不阻塞。 上面的更新代码 为执行者分配5个线程和10个任务。所有未能获得锁定的线程继续打印'for'循环。这意味着当锁定获取线程在“关键部分”工作时,他们“不忙等待”

相比之下,我也实现了同步的方式

import java.util.ArrayList;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Synchronized extends Thread {

    static ExecutorService es = Executors.newFixedThreadPool(5);
    static ArrayList<Object> toBeLocked = new ArrayList<Object>();

    public void methodA() {

        synchronized (toBeLocked) {
            try {
                System.out.println("lock acquired by " + this.getName() + "  of method A");
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                System.out.println("this thread " + this.getName() + "was interrupted");
            }
        }

        for (int i = 0; i < 5; i++) {
            System.out.println("Printed by " + this.getName() + " - " + i);
        }
        System.out.println(this.getName() + " is exiting at time " + new Date(System.currentTimeMillis()));
    }

    @Override
    public void run() {
        methodA();
    }

    public static void main(String args[]) {
        System.out.println(new Date(System.currentTimeMillis()));
        for (int i = 0; i < 10; i++) {
            Runnable r = new Thread(new Synchronized());
            es.submit(r);
        }
        System.out.println(new Date(System.currentTimeMillis()));
    }

}

并发现确实所有这些线程都忙着等待。现在有了这样做的新方法,我观察到所有未能获得锁定的线程都继续前进,从不关心返回。是否有任何设计模式可以回答这两种情况,最佳使用线程池并能够通知下一个最有价值的候选者。