ConCurrent in Practice小记 (2)

Java-ConCurrent2.html

:first-child{margin-top:0!important}img.plugin{box-shadow:0 1px 3px rgba(0,0,0,.1);border-radius:3px}iframe{border:0}figure{-webkit-margin-before:0;-webkit-margin-after:0;-webkit-margin-start:0;-webkit-margin-end:0}kbd{border:1px solid #aaa;-moz-border-radius:2px;-webkit-border-radius:2px;border-radius:2px;-moz-box-shadow:1px 2px 2px #ddd;-webkit-box-shadow:1px 2px 2px #ddd;box-shadow:1px 2px 2px #ddd;background-color:#f9f9f9;background-image:-moz-linear-gradient(top,#eee,#f9f9f9,#eee);background-image:-o-linear-gradient(top,#eee,#f9f9f9,#eee);background-image:-webkit-linear-gradient(top,#eee,#f9f9f9,#eee);background-image:linear-gradient(top,#eee,#f9f9f9,#eee);padding:1px 3px;font-family:inherit;font-size:.85em}.oembeded .oembed_photo{display:inline-block}img[data-echo]{margin:25px 0;width:100px;height:100px;background:url(../img/ajax.gif) center center no-repeat #fff}.spinner{display:inline-block;width:10px;height:10px;margin-bottom:-.1em;border:2px solid rgba(0,0,0,.5);border-top-color:transparent;border-radius:100%;-webkit-animation:spin 1s infinite linear;animation:spin 1s infinite linear}.spinner:after{content:‘‘;display:block;width:0;height:0;position:absolute;top:-6px;left:0;border:4px solid transparent;border-bottom-color:rgba(0,0,0,.5);-webkit-transform:rotate(45deg);transform:rotate(45deg)}@-webkit-keyframes spin{to{-webkit-transform:rotate(360deg)}}@keyframes spin{to{transform:rotate(360deg)}}p.toc{margin:0!important}p.toc ul{padding-left:10px}p.toc>ul{padding:10px;margin:0 10px;display:inline-block;border:1px solid #ededed;border-radius:5px}p.toc li,p.toc ul{list-style-type:none}p.toc li{width:100%;padding:0;overflow:hidden}p.toc li a::after{content:"."}p.toc li a:before{content:"? "}p.toc h5{text-transform:uppercase}p.toc .title{float:left;padding-right:3px}p.toc .number{margin:0;float:right;padding-left:3px;background:#fff;display:none}input.task-list-item{margin-left:-1.62em}.markdown{font-family:"Hiragino Sans GB","Microsoft YaHei",STHeiti,SimSun,"Lucida Grande","Lucida Sans Unicode","Lucida Sans",‘Segoe UI‘,AppleSDGothicNeo-Medium,‘Malgun Gothic‘,Verdana,Tahoma,sans-serif;padding:20px}.markdown a{text-decoration:none;vertical-align:baseline}.markdown a:hover{text-decoration:underline}.markdown h1{font-size:2.2em;font-weight:700;margin:1.5em 0 1em}.markdown h2{font-size:1.8em;font-weight:700;margin:1.275em 0 .85em}.markdown h3{font-size:1.6em;font-weight:700;margin:1.125em 0 .75em}.markdown h4{font-size:1.4em;font-weight:700;margin:.99em 0 .66em}.markdown h5{font-size:1.2em;font-weight:700;margin:.855em 0 .57em}.markdown h6{font-size:1em;font-weight:700;margin:.75em 0 .5em}.markdown h1+p,.markdown h1:first-child,.markdown h2+p,.markdown h2:first-child,.markdown h3+p,.markdown h3:first-child,.markdown h4+p,.markdown h4:first-child,.markdown h5+p,.markdown h5:first-child,.markdown h6+p,.markdown h6:first-child{margin-top:0}.markdown hr{border:1px solid #ccc}.markdown p{margin:1em 0;word-wrap:break-word}.markdown ol{list-style-type:decimal}.markdown li{display:list-item;line-height:1.4em}.markdown blockquote{margin:1em 20px}.markdown blockquote>:first-child{margin-top:0}.markdown blockquote>:last-child{margin-bottom:0}.markdown blockquote cite:before{content:‘\2014 \00A0‘}.markdown .code{border-radius:3px;word-wrap:break-word}.markdown pre{border-radius:3px;word-wrap:break-word;border:1px solid #ccc;overflow:auto;padding:.5em}.markdown pre code{border:0;display:block}.markdown pre>code{font-family:Consolas,Inconsolata,Courier,monospace;font-weight:700;white-space:pre;margin:0}.markdown code{border-radius:3px;word-wrap:break-word;border:1px solid #ccc;padding:0 5px;margin:0 2px}.markdown img{max-width:100%}.markdown mark{color:#000;background-color:#fcf8e3}.markdown table{padding:0;border-collapse:collapse;border-spacing:0;margin-bottom:16px}.markdown table tr td,.markdown table tr th{border:1px solid #ccc;margin:0;padding:6px 13px}.markdown table tr th{font-weight:700}.markdown table tr th>:first-child{margin-top:0}.markdown table tr th>:last-child{margin-bottom:0}.markdown table tr td>:first-child{margin-top:0}.markdown table tr td>:last-child{margin-bottom:0}.github{padding:20px;font-family:"Helvetica Neue",Helvetica,"Hiragino Sans GB","Microsoft YaHei",STHeiti,SimSun,"Segoe UI",AppleSDGothicNeo-Medium,‘Malgun Gothic‘,Arial,freesans,sans-serif;font-size:15px;background:#fff;line-height:1.6;-webkit-font-smoothing:antialiased}.github a{color:#3269a0}.github a:hover{color:#4183c4}.github h2{border-bottom:1px solid #e6e6e6;line-height:1.6}.github h6{color:#777}.github hr{border:1px solid #e6e6e6}.github pre>code{font-size:.9em;font-family:Consolas,Inconsolata,Courier,monospace}.github blockquote>code,.github h1>code,.github h2>code,.github h3>code,.github h4>code,.github h5>code,.github h6>code,.github li>code,.github p>code,.github td>code{background-color:rgba(0,0,0,.07);font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:85%;padding:.2em .5em;border:0}.github blockquote{border-left:4px solid #e6e6e6;padding:0 15px;font-style:italic}.github table{background-color:#fafafa}.github table tr td,.github table tr th{border:1px solid #e6e6e6}.github table tr:nth-child(2n){background-color:#f2f2f2}.hljs{display:block;overflow-x:auto;padding:.5em;color:#333;background:#f8f8f8;-webkit-text-size-adjust:none}.diff .hljs-header,.hljs-comment,.hljs-javadoc{color:#998;font-style:italic}.css .rule .hljs-keyword,.hljs-keyword,.hljs-request,.hljs-status,.hljs-subst,.hljs-winutils,.nginx .hljs-title{color:#333;font-weight:700}.hljs-hexcolor,.hljs-number,.ruby .hljs-constant{color:teal}.hljs-dartdoc,.hljs-phpdoc,.hljs-string,.hljs-tag .hljs-value,.tex .hljs-formula{color:#d14}.hljs-id,.hljs-title,.scss .hljs-preprocessor{color:#900;font-weight:700}.hljs-list .hljs-keyword,.hljs-subst{font-weight:400}.hljs-class .hljs-title,.hljs-type,.tex .hljs-command,.vhdl .hljs-literal{color:#458;font-weight:700}.django .hljs-tag .hljs-keyword,.hljs-rules .hljs-property,.hljs-tag,.hljs-tag .hljs-title{color:navy;font-weight:400}.hljs-attribute,.hljs-variable,.lisp .hljs-body{color:teal}.hljs-regexp{color:#009926}.clojure .hljs-keyword,.hljs-prompt,.hljs-symbol,.lisp .hljs-keyword,.ruby .hljs-symbol .hljs-string,.scheme .hljs-keyword,.tex .hljs-special{color:#990073}.hljs-built_in{color:#0086b3}.hljs-cdata,.hljs-doctype,.hljs-pi,.hljs-pragma,.hljs-preprocessor,.hljs-shebang{color:#999;font-weight:700}.hljs-deletion{background:#fdd}.hljs-addition{background:#dfd}.diff .hljs-change{background:#0086b3}.hljs-chunk{color:#aaa}.MathJax_Hover_Frame{border-radius:.25em;-webkit-border-radius:.25em;-moz-border-radius:.25em;-khtml-border-radius:.25em;box-shadow:0 0 15px #83A;-webkit-box-shadow:0 0 15px #83A;-moz-box-shadow:0 0 15px #83A;-khtml-box-shadow:0 0 15px #83A;border:1px solid #A6D!important;display:inline-block;position:absolute}.MathJax_Hover_Arrow{position:absolute;width:15px;height:11px;cursor:pointer}#MathJax_About{position:fixed;left:50%;width:auto;text-align:center;border:3px outset;padding:1em 2em;background-color:#DDD;color:#000;cursor:default;font-family:message-box;font-size:120%;font-style:normal;text-indent:0;text-transform:none;line-height:normal;letter-spacing:normal;word-spacing:normal;word-wrap:normal;white-space:nowrap;float:none;z-index:201;border-radius:15px;-webkit-border-radius:15px;-moz-border-radius:15px;-khtml-border-radius:15px;box-shadow:0 10px 20px gray;-webkit-box-shadow:0 10px 20px gray;-moz-box-shadow:0 10px 20px gray;-khtml-box-shadow:0 10px 20px gray;filter:progid:DXImageTransform.Microsoft.dropshadow(OffX=2, OffY=2, Color=‘gray‘, Positive=‘true‘)}.MathJax_Menu{position:absolute;background-color:#fff;color:#000;width:auto;padding:5px 0;border:1px solid #CCC;margin:0;cursor:default;font:menu;text-align:left;text-indent:0;text-transform:none;line-height:normal;letter-spacing:normal;word-spacing:normal;word-wrap:normal;white-space:nowrap;float:none;z-index:201;border-radius:5px;-webkit-border-radius:5px;-moz-border-radius:5px;-khtml-border-radius:5px;box-shadow:0 10px 20px gray;-webkit-box-shadow:0 10px 20px gray;-moz-box-shadow:0 10px 20px gray;-khtml-box-shadow:0 10px 20px gray;filter:progid:DXImageTransform.Microsoft.dropshadow(OffX=2, OffY=2, Color=‘gray‘, Positive=‘true‘)}.MathJax_MenuItem{padding:1px 2em;background:0 0}.MathJax_MenuArrow{position:absolute;right:.5em;color:#666}.MathJax_MenuActive .MathJax_MenuArrow{color:#fff}.MathJax_MenuArrow.RTL{left:.5em;right:auto}.MathJax_MenuCheck{position:absolute;left:.7em}.MathJax_MenuCheck.RTL{right:.7em;left:auto}.MathJax_MenuRadioCheck{position:absolute;left:.7em}.MathJax_MenuRadioCheck.RTL{right:.7em;left:auto}.MathJax_MenuLabel{padding:1px 2em 3px 1.33em;font-style:italic}.MathJax_MenuRule{border-top:1px solid #DDD;margin:4px 3px}.MathJax_MenuDisabled{color:GrayText}.MathJax_MenuActive{background-color:#606872;color:#fff}.MathJax_Menu_Close{position:absolute;width:31px;height:31px;top:-15px;left:-15px}#MathJax_Zoom{position:absolute;background-color:#F0F0F0;overflow:auto;display:block;z-index:301;padding:.5em;border:1px solid #000;margin:0;font-weight:400;font-style:normal;text-align:left;text-indent:0;text-transform:none;line-height:normal;letter-spacing:normal;word-spacing:normal;word-wrap:normal;white-space:nowrap;float:none;box-shadow:5px 5px 15px #AAA;-webkit-box-shadow:5px 5px 15px #AAA;-moz-box-shadow:5px 5px 15px #AAA;-khtml-box-shadow:5px 5px 15px #AAA;filter:progid:DXImageTransform.Microsoft.dropshadow(OffX=2, OffY=2, Color=‘gray‘, Positive=‘true‘)}#MathJax_ZoomOverlay{position:absolute;left:0;top:0;z-index:300;display:inline-block;width:100%;height:100%;border:0;padding:0;margin:0;background-color:#fff;opacity:0;filter:alpha(opacity=0)}#MathJax_ZoomFrame{position:relative;display:inline-block;height:0;width:0}#MathJax_ZoomEventTrap{position:absolute;left:0;top:0;z-index:302;display:inline-block;border:0;padding:0;margin:0;background-color:#fff;opacity:0;filter:alpha(opacity=0)}.MathJax_Preview{color:#888}#MathJax_Message{position:fixed;left:1px;bottom:2px;background-color:#E6E6E6;border:1px solid #959595;margin:0;padding:2px 8px;z-index:102;color:#000;font-size:80%;width:auto;white-space:nowrap}#MathJax_MSIE_Frame{position:absolute;top:0;left:0;width:0;z-index:101;border:0;margin:0;padding:0}.MathJax_Error{color:#C00;font-style:italic}footer{position:fixed;font-size:.8em;text-align:right;bottom:0;margin-left:-25px;height:20px;width:100%}
-->

ConCurrent in Practice小记 (2)

Java7 Concurrency Cookbook

裸线程控制(Thread Control)

Thread Interrupt

Thread的interrupt()方法使得线程中断,而检测Thread中断有两个方法,isInterrupt()和interrupted(),这里的interrupted()方法是静态方法,并且在得到interrupt属性值后会将其再置为false,但是isInterrupted仅仅返回属性值。
一般建议使用isInterrupted()

当Thread处于sleep状态的时候,CPU系统会离开该任务而去执行其他的任务,但是一旦interrupt指令出现,则无论Thread在什么状态,立即响应interrupt。

在API中也可以调用yield()来使得CPU离开当前线程的任务去执行其他的任务,JVM会保证任务的执行。

Thread的汇合控制

对裸的Thread汇合控制,即等待某些线程的结束进行下一个线程内容的执行,可以用join控制。用法是在当前线程A中调用另一线程B的join方法,会让线程A等待B的执行完成,然后再执行线程A后的代码。

守护线程(Daemon Thread)

守护线程是Java中一种特殊的线程,该线程的优先级特别低,通常是在系统没有任务执行时才去执行的线程;并且该类线程在JVM中,当其他正常线程都结束时,此时无论守护线程是否还在工作,是否还存在都会使得JVM退出。

所以该类线程通常是给别的线程提供服务的,该类线程最知名的代表是GC(Garbage Collection)。

在线程初始化后可以将线程设置为Daemon,但是一旦start就不能再改变线程的属性。

Thread 未检查异常

Thread中出现UncaughtException,JVM会寻找3中handler来处理;

  1. 会在当前线程的对象中寻找handle,
  2. 当前线程对象中找不到就到线程对象的ThreadGroup中找
  3. 如果扔不存在,JVM则会寻找默认非捕捉异常的handle。

最后,如果异常仍未被处理,JVM则会终止程序,打印异常到控制台。

本地线程变量

本地线程变量要解决的问题是当多个线程可以访问同一个对象的变量(非静态)时,任意一个线程对该对象的属性的改变都会体现在其他线程中。(本质是后一次线程对之前线程中对对象的数据(属性)的修改会覆盖。)

要解决这个问题,就是使用本地线程变量,每个线程维护自己的变量,对其他线程不可见。

这里先记要点,具体的补充等以后再说,要点:

  • 内部维护一个ThreadlocalMap来储存每一个Thread访问对象,并将其作为key值,内部存储的副本作为value。
  • 共有四个方法,get,set,initialValue,remove
  • JDK1.5后都使用泛型
  • 不知道为什么一般都声明为static,甚至还有final的。

还包括子类InheritableThreadLocal,即在里面线程里面再开线程得到的线程中本身就有母线程的本地变量,应该也是维护自己的本地变量。

线程组ThreadCroup

线程组应用的场合主要在于多条线程完成同一份工作,一般只要有一个得到结果就可以结束整个任务过程。

线程工厂

设计模式中的工厂模式,产生一系列新的对象而已。也可以自己实现,ThreadFactory接口中仅仅有一个newThread方法需要实现。

同步问题

同步是解决当不同的线程访问共享的资源时,出现的数据不一致问题。

临界区:包含有共享资源,同一时刻不能有多个线程访问的代码块。 (特别地:由于静态方法同对象方法是不同的存储空间和方式,因此即使对一个对象加锁,但是仍然会出现一个线程访问静态方法,而另一个方法访问该对象的对象方法的情况。此时如果两个方法影响同一个对象的变量,还是会出现同步问题。)

Synchronized关键词

Synchronized是Java并发中最古老的同步语句, 强调!!:永远是对对象加锁!!,所有的方法,即属性加锁,本质上都是对对象的锁。正是Java每个对象的内部锁机制,使得当不同的线程访问同一对象时,才控制对属性的访问权限。

Tips:
由于竞争中的线程拿不到资源就会等待,因此应该尽量减少synchronized关键字的作用域,所以有时候使用代码快的同步:并且有可能直接拿一个object作为同步锁标志代替this。一般是在独立属性的访问中使用非this的方式。

synchronized(this){
    //JavaCode
}

Synchronized是可重入的,因此得到锁的线程可以递归调用synchronized方法。

同步中使用条件

基本的条件语句就是wait(),notify(),notifyAll().
同步中使用条件的最典型应用就是简单的生产消费者模型,两边维护一个队列,当达到一定的长度的时候就阻塞,阻塞使用wait()让生产者停止加入队列,同时notify()通知其他线程的消费者来取;同样地,当消费者取到了队列的尾部,同样自己wait(),并通知其他线程的生产者进行生产notify().

Lock

Synchronized的缺陷:
由于Synchronized是依据对象的内部锁来进行对线程访问加锁的,因此会出现一下缺陷。

  1. 当某一线程已经获得锁时,其他线程只能等待,如果此线程中有耗时操作或者等待,就只能持续下去,不能打断。仅当其释放锁或者发生异常才能得到锁。
  2. 针对读写操作,多个读写线程中,读写和写写线程之间应当加锁,但是读读线程之间不需要,synchronized做不到。

所以在Java1.5之后引入了一个Lock的类,不同于原生的synchronized,用于实现Lock的功能。
Lock类的使用:

如下面的示例

public class Test {
    private ArrayList<Integer> arrayList = new ArrayList<Integer>();
    public static void main(String[] args)  {
        final Test test = new Test();

        new Thread(){
            public void run() {
                test.insert(Thread.currentThread());
            };
        }.start();

        new Thread(){
            public void run() {
                test.insert(Thread.currentThread());
            };
        }.start();
    }

    public void insert(Thread thread) {
        Lock lock = new ReentrantLock();    //注意这个地方
        lock.lock();
        try {
            System.out.println(thread.getName()+"得到了锁");
            for(int i=0;i<5;i++) {
                arrayList.add(i);
            }
        } catch (Exception e) {
            // TODO: handle exception
        }finally {
            System.out.println(thread.getName()+"释放了锁");
            lock.unlock();
        }
    }
}

这里,lock是在一个方法中的局部变量,因此在多个线程访问时,会每一个线程保存一个lock的副本,实际上并没有起到同步的作用。
正确的做法应该是将lock作为类的独立属性来对待。

tryLock的使用:

        if(lock.tryLock()) {
            try {
                System.out.println(thread.getName()+"得到了锁");
                for(int i=0;i<5;i++) {
                    arrayList.add(i);
                }
            } catch (Exception e) {
                // TODO: handle exception
            }finally {
                System.out.println(thread.getName()+"释放了锁");
                lock.unlock();
            }
        } else {
            System.out.println(thread.getName()+"获取锁失败");
        }

记住:!!!永远在finally中手动释放锁,否则会引发死锁。

lockInterruptly()的用法:

public class Test {
    private Lock lock = new ReentrantLock();
    public static void main(String[] args)  {
        Test test = new Test();
        MyThread thread1 = new MyThread(test);
        MyThread thread2 = new MyThread(test);
        thread1.start();
        thread2.start();

        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        thread2.interrupt();
    }

    public void insert(Thread thread) throws InterruptedException{
        lock.lockInterruptibly();   //注意,如果需要正确中断等待锁的线程,必须将获取锁放在外面,然后将InterruptedException抛出
        try {
            System.out.println(thread.getName()+"得到了锁");
            long startTime = System.currentTimeMillis();
            for(    ;     ;) {
                if(System.currentTimeMillis() - startTime >= Integer.MAX_VALUE)
                    break;
                //插入数据
            }
        }
        finally {
            System.out.println(Thread.currentThread().getName()+"执行finally");
            lock.unlock();
            System.out.println(thread.getName()+"释放了锁");
        }
    }
}

class MyThread extends Thread {
    private Test test = null;
    public MyThread(Test test) {
        this.test = test;
    }
    @Override
    public void run() {

        try {
            test.insert(Thread.currentThread());
        } catch (InterruptedException e) {
            System.out.println(Thread.currentThread().getName()+"被中断");
        }
    }
}

记得抛出异常。这里等待得到锁的线程可以被打断。

ReadWriteLock的使用:
ReentrantReadWriteLock是ReadWriteLock的唯一实现,目的是实现在读写过程中的接口分离,这里的lock对象具有两个锁,一个readLock,一个writeLock,两者互不干扰。
用法:

ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
lock.readLock.lock();
//Java code
lock.readLock.unlock();

.............
lock.writeLock.lock();
//Java code
lock.writeLock.unlock();

总结:

  1. synchronized是语言的内置机制,而lock只是一个普通类。
  2. lock的使用中必须记得释放锁,synchronized本身出现异常时,JVM会将异常抛出且释放锁,但是lock包不会,因此必须将unlock()写在finaly中。
  3. lock可以使用tryLock()看是否能得到锁,然后立即返回,不需要一直等待。
  4. lock可以使用中断等待锁的机制。
  5. lock可以实现多路读写的接口分离。
  6. 性能上lock略高。

公平锁

在初始化锁时,增加一个boolean值,是否启用公平锁,启用之后就会使得等待时间最长的线程优先得到锁。而不是多个线程去竞争。

在Lock中使用Condition条件

Condition类是取代之前和synchronized配合的条件类型的,如wait(),notifyAll()。所有的Condition都依赖于lock类,通过lock类中的newCondition()方法得到。对Condition的使用都在lock的lock()和unlock()作用域之间。

Condition的await()用来取代原来的wait(),signal(),signalAll()分别代替原来的notify().notifyAll()。
特别地:注意!当调用await(),对象释放锁,另一个线程可以得到执行。但是对于调用了signalAll()之后,其他相关的线程都会被唤醒,而当某一个线程开始执行,并不能保证其余的线程依然睡眠,因此应该将await()放入while中。原文如下:
When a thread calls the signal() or signallAll() methods of a condition, one or all of the threads that were waiting for that condition are woken up, but this doesn’t guarantee that the condition that made them sleep is now true, so you must put the await() calls inside a while loop.You can’t leave that loop until the condition is true. While the condition is false, you must call await() again.

如果在某个condition上调用了await(),但是没有调用signal(),那么该线程会永远沉睡。

另外:await()的其他版本:
await(long time, TimeUnit unit) 该对象会被以下条件唤醒,(1)时间到,(2)被中断,(3)被signal()唤醒。
awaitUninterruptibly(): 该线程不会被打断,一直到有signal()出现。
awaitUntil(Date date): 类似上面的有时间的版本。
读写锁也可以和condition一起使用。

generated by haroopad

时间: 2025-01-04 16:44:31

ConCurrent in Practice小记 (2)的相关文章

ConCurrent in Practice小记 (3)

高级同步技巧 Semaphore Semaphore信号量,据说是Dijkstra大神发明的.内部维护一个许可集(Permits Set),用于发放许可和回收许可,存在内部计数器,主要用来计数能否得到资源(一般用来限制同时访问资源数).当一个线程拿到许可,计数器减一:当线程释放资源则计数器加一:当计数器为0则阻塞线程. 特别地: Semaphore的同步锁机制仅仅用于对访问许可的同步,对于需要访问对象的池等的同步锁并不保证.如一个线程池需要访问一个资源池,此时对于每一个需要访问资源的线程,要先获

并发理解(阻塞队列)

一.java中阻塞队列如何设计 关于java中的阻塞队列 队列非常适合于生产者/消费者这种业务场景,像rabbitMq,activeMq都是对queue的一个封装的中间件. java中提供了阻塞队列的实现. Queue是接口,定义了存取这些基本接口: public interface Queue<E> extends Collection<E> { //放入到队列,如果放不进则抛错,成功返回true boolean add(E e); //放入queue,返回成功或失败 boole

用happen-before规则重新审视DCL(转)

1.http://www.iteye.com/topic/260515 编写Java多线程程序一直以来都是一件十分困难的事,多线程程序的bug很难测试,DCL(Double Check Lock)就是一个典型,因此对多线程安全的理论分析就显得十分重要,当然这决不是说对多线程程序的测试就是不必要的.传统上,对多线程程序的分析是通过分析操作之间可能的执行先后顺序,然而程序执行顺序十分复杂,它与硬件系统架构,编译器,缓存以及虚拟机的实现都有着很大的关系.仅仅为了分析多线程程序就需要了解这么多底层知识确

Java-SynchronousQueue 阻塞队列小记

在BlockingQueue的子类中有一个SynchronousQueue(同步队列)比较少见,现在做一个简单的介绍,并附加一个简单的例子. SynchronousQueue --JDK1.6介绍: public class SynchronousQueue<E> extends AbstractQueue<E> implements BlockingQueue<E>, Serializable 一种阻塞队列,其中每个插入操作必须等待另一个线程的对应移除操作 ,反之亦然

Java Concurrency In Practice -Chapter 2 Thread Safety

Writing thread-safe code is managing access to state and in particular to shared, mutable state. Object's state is its data, stored in state variables such as instance or static fields. Whether an object needs to be thread-safe depends on whether it

Architectures for concurrent graphics processing operations

BACKGROUND 1. Field The present invention generally relates to rendering two-dimension representations from three-dimensional scenes, and more particularly to using ray tracing for accelerated rendering of photo-realistic two-dimensional representati

Java并发编程:Concurrent锁机制解析

.title { text-align: center } .todo { font-family: monospace; color: red } .done { color: green } .tag { background-color: #eee; font-family: monospace; padding: 2px; font-size: 80%; font-weight: normal } .timestamp { color: #bebebe } .timestamp-kwd

SpringBoot - 二零一七0421小记

一.SpringBoot使用起来比起SpringMVC更便捷,在注解上的小变化,我记录了下面几个: @Controller + @ResponseBody = SpringMVC中用@RestController来代替前面两个注解,通过这个注解,可以将所有的前端http请求放入SpringBoot的Controller容器中,并返回json格式的数据给前端 @RequestMapping(value={"/hello","/hi"},method=RequestMe

hdu 1094 A+B for Input-Output Practice (VI)

A+B for Input-Output Practice (VI) Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 63087    Accepted Submission(s): 42387 Problem Description Your task is to calculate the sum of some integers.