1. 实现线程的两种方式TraditionalThread
继承Thread类,实现implements Runable接口
2. Timer/TimerTask定时器使用(53) TraditionalTimerTest
题目:写一个Timer实现输出一个字符串,第一次间隔2s,第二次间隔4s,第三次间隔2s,交替进行。两种实现(使用一个Timer,使用两个Timer)。
注意:匿名内部类中不能定义static变量。
更好的开源框架学习:quartz
3. 线程互斥技术(synchronized)(54)TraditionalThreadSynchronized
类似银行转账问题
案例:分别启动两个线程安字母打印名字循环输出,使用synchronized实现互斥
注意:内部类中访问局部变量需加final。
如果使用多个synchronized会出现死锁现象。
静态的方法锁“门栓”是当前类的class,普通方法的“门栓”是this。
要实现互斥,synchronized所使用的“门栓”必须相同。
4. 线程同步通信技术(wait,notify)(54)TraditionalThreadCommunication
自动登录案例,加密和解密cookie的实现,好处高内聚低耦合。
面试题:子线程循环10次,主线程循环5次,两者交替运行50次。
推荐写法:
synchronized (obj) {
while (<condition does not hold>)
obj.wait();
... // Perform action appropriate to condition
}
关于线程同步的代码是写在共享变量中的不要写在线程中使用。
5. 线程范围内共享变量(ThreadLocal)ThreadScopeShareData(57)
实现:Map<Thread,Object> 在get取值的使用从map中取得数据。分别得到的数据是属于这个线程的。保证了在该线程中操作的对象不会干扰别的线程。
- 多个线程访问共享对象和数据的方式
- 如果每个线程执行的代码相同,可以使用同一个Runnable对象,这个Runnable对象中有的数据就是共享数据.例如,卖票系统
- 如果每个线程执行的代码不同,这时需要用不同的Runnable对象,有如下两种方式来实现这些Runnable对象之间的数据共享:
a) 将共享数据封装在另外一个对象中,然后将这个对象逐一传递给各个Runnable对象。每个线程对共享数据的操作方法也分配到那个对象上面去完成,这样容易实现针对该数据进行的各个操作的互斥和通信。(传入runnable)
b) 将这些Runnable对象作为某一个class中的内部类,共享数据作为这个外部类中的成员变量,每个线程对共享数据的操作方法也分配给外部类,以便实现对共享数据进行的各个操作的互斥和通信,作为内部类的各个Runnable对象调用外部class的这些方法. (runnable去共同方法去取)
c) 前两种方式组合:将共享数据封装在另一个对象中,每个线程对共享数据的操作方法也分配到那个对象身上去完成,对象作为这个外部类中的成员变量或方法中的局部变量,每个线程的Runnable对象作为外部类中的成员内部类或局部内部类。
总结:要同步互斥的几段代码最好分别放在几个独立的方法中,这些方法再放在同一个类中,这样比较容易实现他们之间的线程同步互斥和通信。
最极端且简单的方式,就是在任何一个class中或者接口中定义public static变量,这个变量将被所有线程共享。
总结中有部分代码没有上传,请大家可以在评论中给出答案哈!