1, Process&Threads

Most implementations of the Java virtual machine run as a single process.

Threads exist within a process — every process has at least one. Threads share the process's resources, including memory and open files. This makes for efficient, but potentially problematic, communication.

From the application programmer's point of view, you start with just one thread, called the main thread. This thread has the ability to create additional threads, as we'll demonstrate in the next section.

2, Interrupt

Interruption in Java is not pre-emptive. Put another way both threads have to cooperate in order to process the interrupt properly. If the target thread does not poll the interrupted status the interrupt is effectively ignored.

Polling occurs via the Thread.interrupted() method which returns the current thread's interrupted status AND clears that interrupt flag. Usually the thread might then do something such as throw InterruptedException.

Some API methods have built in interrupt handling. Of the top of my head this includes.

  • Object.wait()/Thread.sleep()
  • Most java.util.concurrent structures
  • Java NIO (but not java.io) and it does NOT use InterruptedException, instead using ClosedByInterruptException.

Interrupts are not explicitly handled by synchronization - synchronous blocks only gaurantee that, while executing, the block cannot be reentered by another thread.

总结: 对于像sleep()这样的方法,会自己throw InterrupttedException,如果你有程序会扔出这个interrupt,那编程的时候就catch它进行处理。否则,直接将当前方法throws InterruptedException即可。

或者自己调用Thread.interrupted()方法检测Interrupted status并进行处理。

对于一般的synchronized method,不会自动处理Interrupt并退出。

3,Java memory model

总结:在单线程的情况下,compiler也会对指令重排序来优化运行时间,只要保证说原order和重排序order执行后的结果一致即可。

但是,在多线程的情况下,compiler对线程1的指令重排序会影响线程2的执行结果。所以对于共享内存的多个线程来说,为了达到happens-before效果[即线程1的结果对线程2是可见的],Java memory model定义了多个rules。而这些rules的背后是,java编译器在生成指令序列的适当位置会插入内存屏障指令来禁止特定类型的处理器重排序。

由于: On modern platforms, code is frequently not executed in the order it was written. It is reordered by the compiler, the processor and the memory subsystem to achieve maximum performance. On multiprocessor architectures, individual processors may have their own local caches that are out of sync with main memory. It is generally undesirable to require threads to remain perfectly in sync with one another because this would be too costly from a performance point of view. This means that at any given time, different threads may see different values for the same shared data.

Thread 1 Thread 2
x = 1; int r1 = y;
y = 2; int r2 = x;

If no reorderings are performed, and the read of y in Thread 2 returns the value 2, then the subsequent read of x should return the value 1, because the write to x was performed before the write to y. However, if the two writes are reordered, then the read of y can return the value 2, and the read of x can return the value 0.

因此: The Java Memory Model (JMM) defines the allowable behavior of multithreaded programs, and therefore describes when such reorderings are possible. It places execution-time constraints on the relationship between threads and main memory in order to achieve consistent and reliable Java applications.

Rules that Java Memory Model uses to guarantee happens-before:

1、程序次序规则:在一个单独的线程中,按照程序代码的执行流顺序,(时间上)先执行的操作happen—before(时间上)后执行的操作。

2、管理锁定规则:一个unlock操作happen—before后面(时间上的先后顺序,下同)对同一个锁的lock操作。

3、volatile变量规则:对一个volatile变量的写操作happen—before后面对该变量的读操作。

...

The basic rules imply that individual actions can be reordered, as long as the as-if-serial semantics of the thread are not violated, and actions that imply communication between threads, such as the acquisition or release of a lock, ensure that actions that happen prior to them are seen by other threads that see their effects. For example, everything that happens before the release of a lock will be seen to be ordered before and visible to everything that happens after a subsequent acquisition of that same lock.

In Java specifically, a happens-before relationship is a guarantee that memory written to by statement A is visible to statement B, that is, that statement A completes its write before statement B starts its read.

A memory barrier, also known as a membar, memory fence or fence instruction, is a type of barrier instruction which causes a central processing unit (CPU) orcompiler to enforce an ordering constraint on memory operations issued before and after the barrier instruction. This typically means that operations issued prior to the barrier are guaranteed to be performed before operations issued after the barrier.

4, Synchronized v.s. Volatile

对一个volatile变量的读,总是能看到(任意线程)对这个volatile变量最后的写入。

加锁机制(即同步机制)既可以确保可见性又可以确保原子性,而volatile变量只能确保可见性,原因是声明为volatile的简单变量如果当前值与该变量以前的值相关,那么volatile关键字不起作用,也就是说如下的表达式都不是原子操作:“count++”、“count = count+1”。

How to synchronize a HashMap?

Map m = Collections.synchronizedMap(new HashMap());
...
Set s = m.keySet(); // Needn't be in synchronized block
...
synchronized (m) { // Synchronizing on m, not s!
Iterator i = s.iterator(); // Must be in synchronized block
while (i.hasNext())
foo(i.next());
}

5, Atomic operations

In concurrent programming, an operation (or set of operations) is atomic, linearizable, indivisible or uninterruptible if it appears to the rest of the system to occur instantaneously.

6, Intrinsic locks

是Synchronization的基础,Synchronized method是获取当前object的instrinsic lock,而Synchronized block是获取某个object的instrinsic lock。

Synchronization is built around an internal entity known as the intrinsic lock. Intrinsic locks play a role in both aspects of synchronization: enforcing exclusive access to an object's state and establishing happens-before relationships that are essential to visibility.Every object has an intrinsic lock associated with it. 

public class MsLunch {
private long c1 = 0;
private long c2 = 0;
private Object lock1 = new Object();
private Object lock2 = new Object();
public void inc1() {
synchronized(lock1) {
c1++;
}
}
public void inc2() {
synchronized(lock2) {
c2++;
}
}
}
什么时候prefer synchronized block?
在这个方法你只想synchronize一部分code。或者像上面这个例子,c1和c2从来不会一起使用,所以没有必要在执行inc2的时候block inc1(),提高了速度。

7, Blocking queue

http://tutorials.jenkov.com/java-concurrency/blocking-queues.html

8, "double-checked locking" pattern

9, ThreadLocal

ThreadLocal和Synchonized都用于解决多线程并发访问。但是ThreadLocal与synchronized有本质的区别。synchronized是利用锁的机制,使变量或代码块在某一时该只能被一个线程访问。而ThreadLocal为每一个线程都提供了变量的副本,使得每个线程在某一时间访问到的并不是同一个对象,这样就隔离了多个线程对数据的数据共享。而Synchronized却正好相反,它用于在多个线程间通信时能够获得数据共享。
 
Synchronized用于线程间的数据共享,而ThreadLocal则用于线程间的数据隔离。
 
当然ThreadLocal并不能替代synchronized,它们处理不同的问题域。Synchronized用于实现同步机制,比ThreadLocal更加复杂。
10, Volatile more

When a field is declared volatile, the compiler and runtime are put on notice that this variable is shared and that operations on it should not be reordered with other memory operations. Volatile variables are not cached in registers or in caches where they are hidden from other processors, so a read of a volatile variable always returns the most recent write by any thread.
When thread A writes to a volatile variable and subsequently thread B reads
that same variable, the values of all variables that were visible to A prior to
writing to the volatile variable become visible to B after reading the volatile
variable. So from a memory visibility perspective, writing a volatile variable
is like exiting a synchronized block and reading a volatile variable is like
entering a synchronized block.
You can use volatile variables only when all the following criteria are met:

  • Writes to the variable
    do not depend on its current value, or you can ensure that only a single thread
    ever updates the value;
  • The variable does not
    participate in invariants with other state variables;

Locking is not required for
any other reason while the variable is being accessed.

11, Mutex vs Semaphore

A mutex provides mutual exclusion, either producer or consumer can have the key (mutex) and proceed with their work. As long as the buffer is filled by producer, the consumer needs to wait, and vice versa.

At any point of time, only one thread can work with the entire buffer. The concept can be generalized using semaphore.

A semaphore is a generalized mutex. Semaphore can be counted, while mutex can only count to 1.

12, java.util.concurrent.locks package

使用Lock是比synchronized更高级的选择,可以添加更多的逻辑。

Interface Lock[methods: lock(), unlock()], Implematations: ReentrantLock, ReadWriteLock

V.S. Synchronized: more extensive locking operations, allow more flexible structuring, may have quite different properties, and may support multiple associated Condition objects. ReadWriteLock may allow concurrent access to a shared resource.

ReentrantLock is different thing with Reentrant Synchronization[Synchronized本身就是默认reentrant的].

package com.journaldev.threads.lock; 
public class SynchronizedLockExample implements Runnable{
    private Resource resource;   
    public SynchronizedLockExample(Resource r){
        this.resource = r;
    }     
    @Override
    public void run() {
        synchronized (resource) {
            resource.doSomething();
        }
        resource.doLogging(); }}
 
package com.journaldev.threads.lock;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ConcurrencyLockExample implements Runnable{
    private Resource resource;
    private Lock lock;     
    public ConcurrencyLockExample(Resource r){
        this.resource = r;
        this.lock = new ReentrantLock();
    }   
    @Override
    public void run() {
        try {
            if(lock.tryLock(10, TimeUnit.SECONDS)){ //Here, better than Synchronized, you could set timeout to not wait forever.
            resource.doSomething();
            }
        catch (InterruptedException e) {
            e.printStackTrace();
        }finally{
            //release lock
            lock.unlock();  //Here, more complicated than Synchronized, you need to use try/finally to release the lock.
        }
        resource.doLogging(); }}

13, ExecutorService

The java.util.concurrent.ExecutorService interface represents an asynchronous execution mechanism which is capable of executing tasks in the background. An ExecutorService is thus very similar to a thread pool.

ExecutorService executorService = Executors.newFixedThreadPool(10);

executorService.execute(new Runnable() {
public void run() {
System.out.println("Asynchronous task");
}
}); executorService.shutdown(); //会通知ExecutorService关闭,它自己会等现有的tasks执行完毕就关闭。如果你不call shutdown(),会导致JVM无法关闭。

创建ExecutorService:

ExecutorService executorService1 = Executors.newSingleThreadExecutor();

ExecutorService executorService2 = Executors.newFixedThreadPool(10);

ExecutorService executorService3 = Executors.newScheduledThreadPool(10);

ExecutorService的方法:

  • execute(Runnable)
  • submit(Runnable)      return Future, 
    future.get();  //returns null if the task has finished correctly.
  • submit(Callable)        return Future, and future.get() return callable.call().
  • future.get() = Callable Result
  • invokeAny(...)
  • invokeAll(...)

Callable: 作用类似于Runnable,不同的是会返回结果.

import java.util.concurrent.Callable;

public class MyCallable implements Callable<Long> {  //Callable是泛型
@Override
public Long call() throws Exception { //要Override T call()方法
long sum = 0;
for (long i = 0; i <= 100; i++) {
sum += i;
}
return sum;
}
}
Callable<Long> worker = new MyCallable();
Future<Long> submit = executor.submit(worker);
public interface Future<V>
Future represents the result of an asynchronous computation. Methods are provided to check if the computation is complete, to wait for its completion, and to retrieve the result of the computation.

The executor framework presented in the last chapter works with Runnables. Runnable do not return result.

In case you expect your threads to return a computed result you can use java.util.concurrent.Callable. TheCallable object allows to return values after completion.

												

[Java Basics] multi-threading的更多相关文章

  1. [Java Basics] Reflection

    For every type of object, the Java virtual machine instantiates an immutable instance of java.lang.C ...

  2. [Java Basics] Collection

    除了Java collection class/interface外,方便的有Google guava的utility class: Lists/Sets/Maps/Queues, 用它们可以方便地创 ...

  3. [Java Basics] Stack, Heap, Constructor, I/O, Immutable, ClassLoader

    Good about Java: friendly syntax, memory management[GC can collect unreferenced memory resources], o ...

  4. Summary of Java basics review data

    1.标识符      用于命名程序的对象,如方法名,变量名,规则是: a.大小写敏感 b.由英文字符,文字字符,美元符号,下划线和数字组成,但不能以数字开头 c.不能是关键字 2.%:求余运算符    ...

  5. java:提示Could not initialize class sun.awt.X11GraphicsEnvironment

    前几天发现tomcat提示 Could not initialize class sun.awt.X11GraphicsEnvironment  问题.以为不验证,就没太关注,今天发现,有同事提示了个 ...

  6. 【转】O'Reilly Java系列书籍建议阅读顺序(转自蔡学庸)

    Learning Java the O'Reilly's Way (Part I) Java 技术可以说是越来越重要了,不但可以用在计算机上,甚至连电视等家电用品,行动电话.个人数字助理(PDA)等电 ...

  7. 【Java】-NO.20.Exam.1.Java.1.001- 【1z0-807】- OCEA

    1.0.0 Summary Tittle:[Java]-NO.20.Exam.1.Java.1.001-[1z0-807] Style:EBook Series:Java Since:2017-10- ...

  8. 【java异常】org.springframework.web.util.NestedServletException: Handler processing failed;Can't connect to X11 window server using 'localhost:10.0' as the value of th

    tomcat工程中创建二维码失败.抛出异常Can't connect to X11 window server using 'localhost:10.0' as the value of th 因为 ...

  9. java 利用ManagementFactory获取jvm,os的一些信息--转

    原文地址:http://blog.csdn.net/dream_broken/article/details/49759043 想了解下某个Java项目的运行时jvm的情况,可以使用一些监控工具,比如 ...

随机推荐

  1. 再次熟悉jdbc连接mysql

    闲来无事想探究一下jdbc 1.首先准备工作.我们要下载jdbc驱动包mysql-connector-java-5.1.7-bin.jar.其他的暂时先不用,这个包的下载地址:http://pan.b ...

  2. Auty自动化测试框架第六篇——垃圾代码回收、添加suite支持

    [本文出自天外归云的博客园] 垃圾代码回收 添加脚本恢复机制,因为框架会自动生成一些代码,如果代码生成后出现问题导致代码没有正常删除掉,则会造成代码垃圾,在auty目录添加recovery.py文件: ...

  3. python(九)re模块

    python中re模块提供了正则表达式相关操作. 1. 字符串匹配: .    匹配除换行符以外的任意字符 \w 匹配字符或数字或下划线或汉字 \s  匹配任意空白字符 \d 匹配数字 \b 匹配单词 ...

  4. Android DiskLruCache 源码解析 硬盘缓存的绝佳方案

    一.概述 依旧是整理东西,所以近期的博客涉及的东西可能会比较老一点,会分析一些经典的框架,我觉得可能也是每个优秀的开发者必须掌握的东西:那么对于Disk Cache,DiskLruCache可以算佼佼 ...

  5. Less 使用指南

    简而言之 Less是为了简化css http://less.bootcss.com/features/ 以上链接是Less中文网站,里面有对Less的详细介绍. 一下写在使用中遇到的问题: 1.下载L ...

  6. JAVA-Semaphore信号灯-可实现维护自身线程访问数

    import java.util.Random; import java.util.concurrent.ExecutorService; import java.util.concurrent.Ex ...

  7. ExtJs

    ExtJS是一种主要用于创建前端用户界面,是一个与后台技术无关的前端ajax框架.      概念 1.ExtJS可以用来开发RIA也即富客户端的AJAX应用,是一个用javascript写的,主要用 ...

  8. JQ写简单的伸缩菜单(内附效果图和源代码)

    效果如图: JQ代码就那么几句, <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "h ...

  9. openurl 跳转

    1.拨打电话: [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"tel://68979"]]; ...

  10. sublime_text3配置

    推荐视频 http://v.youku.com/v_show/id_XMzU5NzQ5ODgw.html 介绍的是2版本 准备工作 点击连接下载Sublime Text3 初始化用户信息 第一次安装该 ...