java多线程(二)

线程优先级

java 中的线程优先级的范围是1~10,默认的优先级是5。“高优先级线程”会优先于“低优先级线程”执行。java 中有两种线程:用户线程和守护线程。可以通过isDaemon()方法来区别它们:如果返回false,则说明该线程是“用户线程”;否则就是“守护线程”。用户线程一般用户执行用户级任务,而守护线程也就是“后台线程”,一般用来执行后台任务。需要注意的是:Java虚拟机在“用户线程”都结束后会后退出。

每个线程都有一个优先级。“高优先级线程”会优先于“低优先级线程”执行。每个线程都可以被标记为一个守护进程或非守护进程。在一些运行的主线程中创建新的子线程时,子线程的优先级被设置为等于“创建它的主线程的优先级”,当且仅当“创建它的主线程是守护线程”时“子线程才会是守护线程”。

当Java虚拟机启动时,通常有一个单一的非守护线程(该线程通过是通过main()方法启动)。JVM会一直运行直到下面的任意一个条件发生,JVM就会终止运行:

(01) 调用了exit()方法,并且exit()有权限被正常执行。

(02) 所有的“非守护线程”都死了(即JVM中仅仅只有“守护线程”)。

实例:

http://git.oschina.net/memristor/javalab/blob/af4cdc76bf722b9e7f33c0a813795ee23bf77b2f/javalab/src/thread/Test/PriorityTest.java

守护进程

例子:

http://git.oschina.net/memristor/javalab/blob/68887ee9bcfc7257cdbe8fab81f035677e2ce338/javalab/src/thread/Test/DaemonThreadTest.java

(01) 主线程main是用户线程,它创建的子线程t1也是用户线程。

(02) t2是守护线程。在“主线程main”和“子线程t1”(它们都是用户线程)执行完毕,只剩t2这个守护线程的时候,JVM自动退出。


生产者消费者问题

(01) 生产者仅仅在仓储未满时候生产,仓满则停止生产。

(02) 消费者仅仅在仓储有产品时候才能消费,仓空则等待。

(03) 当消费者发现仓储没产品可消费时候会通知生产者生产。

(04) 生产者在生产出可消费产品时候,应该通知等待的消费者去消费。

生产者消费者示例

http://git.oschina.net/memristor/javalab/blob/002a37f44e551c40606a2dafe81adea17a57f986/javalab/src/thread/Test/ConsumerProductTest.java


线程之间的通信


方式:共享内存和消息传递

共享内存:线程A和线程B共享内存,线程A更新共享变量的值,刷新到主内存中,线程B去主内存中读取线程A更新后的变量。整个通信过程必须通过主内存。同步是显式进行的。

java多线程(二)

如果一个变量是volatile类型,则对该变量的读写就将具有原子性。如果是多个volatile操作或类似于volatile++这种复合操作,这些操作整体上不具有原子性。

volatile变量自身具有下列特性:

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

[原子性]:对任意单个volatile变量的读/写具有原子性,但类似于volatile++这种复合操作不具有原子性。

volatile写:当写一个volatile变量时,JMM会把该线程对应的本地内存中的共享变量刷新到主内存。

volatile读:当读一个volatile变量时,JMM会把该线程对应的本地内存置为无效。线程接下来将从主内存中读取共享变量。


2 消息传递:消息的发送在消息的接受之前,同步隐式进行。


ThreadLocal 

http://www.iteye.com/topic/103804

ThreadLocal 不是用来解决共享对象的多线程访问问题的,一般情况下,通过ThreadLocal.set() 到线程中的对象是该线程自己使用的对象,其他线程是不需要访问的,也访问不到的.ThreadLocal使得各线程能够保持各自独立的一个对象,并不是通过ThreadLocal.set()来实现的,而是通过每个线程中的new 对象 的操作来创建的对象,每个线程创建一个,不是什么对象的拷贝或副本。通过ThreadLocal.set()将这个新创建的对象的引用保存到各线程的自己的一个map中,每个线程都有这样一个map,执行ThreadLocal.get()时,各线程从自己的map中取出放进去的对象,因此取出来的是各自自己线程中的对象,ThreadLocal实例是作为map的key来使用的。 如果ThreadLocal.set()进去的东西本来就是多个线程共享的同一个对象,那么多个线程的ThreadLocal.get()取得的还是这个共享对象本身,还是有并发访问问题。 

ThreadLocal的一个实现

import java.util.Collections; 
import java.util.HashMap; 
import java.util.Map; 

/** 
* 使用了ThreadLocal的类 
* 
* @author leizhimin 2010-1-5 10:35:27 
*/ 
public class MyThreadLocal { 

        //定义了一个ThreadLocal变量,用来保存int或Integer数据 
        private com.lavasoft.test2.ThreadLocal<Integer> tl = new com.lavasoft.test2.ThreadLocal<Integer>() { 
                @Override 
                protected Integer initialValue() { 
                        return 0; 
                } 
        }; 

        public Integer getNextNum() { 
                //将tl的值获取后加1,并更新设置t1的值 
                tl.set(tl.get() + 1); 
                return tl.get(); 
        } 
} 

class ThreadLocal<T> { 
        private Map<Thread, T> map = Collections.synchronizedMap(new HashMap<Thread, T>()); 

        public ThreadLocal() { 
        } 

        protected T initialValue() { 
                return null; 
        } 

        public T get() { 
                Thread t = Thread.currentThread(); 
                T obj = map.get(t); 
                if (obj == null && !map.containsKey(t)) { 
                        obj = initialValue(); 
                        map.put(t, obj); 
                } 
                return obj; 
        } 

        public void set(T value) { 
                map.put(Thread.currentThread(), value); 
        } 

        public void remove() { 
                map.remove(Thread.currentThread()); 
        } 
}

事实上ThreadLocal是这样做的:

    /**
     * Returns the value in the current thread's copy of this
     * thread-local variable.  If the variable has no value for the
     * current thread, it is first initialized to the value returned
     * by an invocation of the {@link #initialValue} method.
     *
     * @return the current thread's value of this thread-local
     */
    public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null)
                return (T)e.value;
        }
        return setInitialValue();
    }


你可能感兴趣的:(java,多线程,threadLocal)