多线程:
多线程机制会提高程序的运行效率吗?为什么会有多线程下载呢?
答:对于单核CPU,多线程只有运用在类似于多线程的下载时才会运行效率高。否则,性能反而降低。
Timer类:定时器
常见方法:
schedule(TimerTask task, Date time)
安排在指定的时间执行指定的任务。
schedule(TimerTask task, long delay)
安排在指定延迟后执行指定的任务。
schedule(TimerTask task, Date firstTime, long period)
安排指定的任务在指定的时间开始进行重复的固定延迟执行。
另有开源的工具quartz 来解决这样样的问题。
线程的互斥和同步:
匿名内部类方法访问局部变量时,"局部变量"需要使用final修饰。
静态方法内不能new内部类的实例对象。因为,在static方法中的对象不需要创建一个类的实例对象就可访问,
而内部类必须需要一个外部类对象才能访问,这样就反生了冲突。所以可以将整个代码块封装成一个init()的成员方法,
再通过创建一个外部类的对象来调用这个方法即可。
静态方法使用synchronized修饰时,必须在一个静态的内部类中(此时这个内部类就可以看作一个最外层的类)
或是作为最外层类的成员方法。其原理在于“生命周期的问题”--静态方法的生命周期不能比他所在的类的周期长,
而内部类也同样不能比其外部类的生命周期长引起的。
静态的方法直接跟字节码文件相关联。
将将关联的需要同步的代码块分别封装成相应的方法并放入新定义的同一个类中,
这样就可以避免了字节码作为同步锁的锁资源匮乏问题。
使用这种设计模式:将要用到共同数据(包括同步锁)或共同方法的若干个方法应该归在同一个类身上,
这种设计正好体现了高类聚的健壮性。
互斥和同步的操作都是在这个资源的类中实现。
线程范围内的共享变量:
我一件事,只在我的这个线程内搞定,不要影响其他线程的事。我这个线程内的几个模块是独立的,并共享同一数据。“在线程内共享,在线程外独立”。
在java中为专门提供了一个ThreadLocal类来实现线程范围内的共享变量。
如: private static ThreadLocal<Integer> x = new ThreadLocal<Integer>();
如果程序里面有N个变量都是线程程序中所共享的怎么办能呢?
由于一个ThreadLocal只能代表一个变量,故其中只能放一个数据,若有多个变量都要线程范围内共享,则要定义多个ThreadLocal对象。这样就很麻烦,
这时有一个好的方法可以解决这样的问题。就是把这N个变量定义为一个实体,就把这个实体作为一个变量存储在ThreadLocal里面。
同时,需要把ThreadLocal作为类的内部成员,将通过懒汉式的单例设计模式获得的实例赋值给它,就实现了单个线程的绑定。
线程并发库:
Java jdk1.5新特性之一。
进入了java.util.concurrent.atomic包,使用这个包中的方法,可以对基本数据、数组的基本数据、类中基本数据进行操作。
线程池(ExecutorService):
线程池的创建和类型:
固定的线程池: ExecutorService threadPool = Executors.newFixedThreadPool(3);
缓存的线程池: ExecutorService threadPool = Executors.newCachedThreadPool();
单一线程池: ExecutorService threadPool = Executors.newSingleThreadExecutor(); //如果该线程死了,可以自动重新创建一个接替的线程
关闭线程池:
shutdown() 与shutdownNow()
线程池启动定时器:
Executors.newScheduledThreadPool(3).schedule(command,dely,unit);
Callable & Future:
他们的作用是我们程序启动一个线程,它可以给我们返回线程执行的结果。
Lock(同步并发) :
在jdk1.5之后使用了lock关键字来代替老版本的synchronized. 此时需要的同步的代码块就在lock();和unlock();方法之间。
读写锁:分为读锁和写锁,多个读锁不互斥,读锁和写锁互斥,写锁和写锁互斥。
在使用ReentrantReadWriteLock读写锁的多线程并发操作时,注意要使用双层嵌套的if判断语句才可以消除写锁的安全隐患,以达到写锁和写锁的互斥。
Condition(通信):
创建: Condition condition = lock.newCondition();
等待:condition.await();
唤醒:condition.signal();
线程同步工具:
Semaphore:通常用于限制可以访问某些资源(物理或逻辑的)的线程数目
CyclicBarrier:一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点。
Exchanger:实现两个线程之间的数据交换。
可阻塞的队列 ArrayBlockingQueue :
队列包含固定长度的队列和不固定长度的队列。
并发集合:
ConcurrentHashMap
ConcurrentSkipListMap
ConcurrentSkipListSet (类似TreeSet)
CopyOnWriteArrayList
CopyOnWriteArraySet
由于HashMap是一个线程不安全的集合,在没有加上同步标志时(在jdk1.5前可以使用HashTable或是Collections.sychronizedMap(new HashMap());),
存在安全隐患。
所以在jdk1.5出现了新的线程安全的集合,可以实现线程的并发访问。这就是 ConcurrentHashMap 集合。
对于线程并发库的知识点有些难度,后期会更新关于线程的专题。