PDF 课件和源代码下载地址:
https://gitee.com/geektime-geekbang/LetsJava
作者回复: 是这样的,synchronized不保证(强调不保证)是公平锁。但是并不代表实际在某个具体程序的某次运行时,他的表现是和公平锁一样的。 只要有不公平的可能,就不能说是公平锁。要能百分之百保证在任何情况下都是公平锁,代价很高。synchronized是随缘公平,不保证公平。
作者回复: 赞!
作者回复: 从程序设计和主管感觉上,是的。但是这相当于是创造了一种比较理想的条件,让主线程排在worker的后面。 为什么呢?后面也会讲到,synchronized不是公平锁,也就是说,是不保证先来先得的。重点词:不保证。不保证的意思是说,不在保证锁的公平性上,花费太多的代价。 但是就我们这个例子来说,主线程因为多sleep了一秒钟,其实并不是一个非常严格的竞争环境,所以除非非常小的几率,否则主线程都还会排在worker线程后面拿到锁。
作者回复: 很好很全面
作者回复: 这个接口如果是http的话,需要自己做一些控制。http本身并没有拉取数据过多导致超时这么个设置,只能说是连不上之类的网络问题导致timeout。 从我理解你的需求来看,即使拉取的数据超过10秒,其实也是在正常传输数据的,http自己不会因为这个断掉。 我的理解是,你这边的程序有个DataPuller,按照主程序的需求,向第三方发起http请求,拉取数据,然后主程序等待DataPuller返回数据,但是最多只想等待10秒,10秒内能结束最好,不能结束就有多少数据就给主程序多少就行了。 下面的示例代码供你参考: https://gist.github.com/deepnighttwo/b760bf0bbaddaaf3d3fb6e331684b54d /** * @author 臧萌 */ public class PullDataWithTimeLimitAppMain { public static void main(String[] args) throws InterruptedException { long start = System.currentTimeMillis(); CountDownLatch countDownLatch = new CountDownLatch(1); PullDataTask task = new PullDataTask(countDownLatch); new Thread(task).start(); System.out.println("Waiting for data pulling"); countDownLatch.await(10, TimeUnit.SECONDS); System.out.println("Finished waiting. Actually waited for " + (System.currentTimeMillis() - start) / 1000 + " sec. Data got from data puller is " + task.getDataList()); } } class PullDataTask implements Runnable { private List<Integer> dataList = new ArrayList<>(); private CountDownLatch countDownLatch; public PullDataTask(CountDownLatch countDownLatch) { this.countDownLatch = countDownLatch; } @Override public void run() { int timeSec = (int) (Math.random() * 20); System.out.println("going to pulling data for " + timeSec + " seconds"); IntStream.range(0, timeSec).forEach(i -> { try { Thread.sleep(TimeUnit.SECONDS.toMillis(1)); } catch (InterruptedException e) { e.printStackTrace(); } dataList.add(i); }); countDownLatch.countDown(); System.out.println("pulling finished"); } public List<Integer> getDataList() { return dataList; } }
作者回复: 我学的时候可能比你还懵。多写,用心去感受:线程是执行代码的。代码是告诉线程执行的命令的
作者回复: 这个和线程的优先级是没关系的。这个例子里,notify线程是最后一个去抢锁的。我们可以假想所有抢锁的线程都在一个队列里等着,那么最后一个抢的,大概率会最后一个抢到。当然Java语言和Java规范并没有这样规定。
作者回复: () -> {} 就是lambda的表达式,也就是Thread执行的实际代码。 这个代码里面就是用sleep模拟工作,用locker去模拟获取不可共享的资源。
作者回复: notify不会释放锁,notify本身是在synchronized里的,synchronized块结束就会释放锁。
作者回复: 本质是一样的,对象上的锁。