一、
设计一个类KillThread继承Thread,并且重写run方法
启动线程办法:实例化一个KillTHread对象,并且调用其start方法
二、
创建类Battle,实现Runnable接口
启动的时候,首先创建一个Battle对象,然后再根据该battle对象创建一个线程对象,并启动
Battle battle1 = new Battle(gareen, teemo);
new Thread(battle1).start;
battle1 对象实现了Runnable接口,所以有run方法,但是直接调用run方法,并不会启动一个新的线程。
必须,借助一个线程对象的start()方法,才会启动一个新的线程。
所以,在创建Thread对象的时候,把battle1作为构造方法的参数传递进去,这个线程启动的时候,就会去执行battle1.run()方法了。
三、匿名类
使用匿名类,继承Thread,重写run方法,直接在run方法中写业务代码
匿名类的一个好处是可以很方便的访问外部的局部变量
前提是外部的局部变量需要被声明为final(JDK7以后就不需要了)
总结:
1.继承Thread类
2.实现Runnable接口
3.匿名类的方式
其他一些指令
ti.join();加入进程
t1.setPriority();设置进程的优先级 Thread.MAX_PRIORITY,Thread.MIN_PRIORITY
临时暂停:Thread.yield();
设置守护线程:t1.setDaemon(true);一个进程中,不可全是守护进程
三、同步
加入synchronized(someObject);
Thread t = new Thread(){
public void run(){
synchronized(someObject){
gareen.recover();
}
}
}
2.使用自身对象作为同步对象
例如:synchronized (this) {
}
public synchronized void recover(){
}
线程安全的类:方法都是有synchronized修饰的,那么该类就叫做线程安全的类
StringBuffer 的方法都是有synchronized修饰的,StringBuffer就叫做线程安全的类
而StringBuilde就不是线程安全的类
具体类比较:
区别1:
HashMap可以存放null
Hashtable不能存放null
区别2:
HashMap不是线程安全的类
Hashtable是线程安全的类
区别3:
StringBuffer是线程安全的
StringBuilder是非线程安全的
区别四:
Vector是线程安全的类,而ArrayList是非线程安全的类
四、把非线程安全的集合转换为线程安全
例如:
List<Integer> list1 = new ArrayList<>();
List<Integer> list2 = Collections.synchronizedList(list1);
五、死锁
Thread t3 =
new
Thread(){
public
void
run(){
synchronized
(b) {
try
{
Thread.sleep(
1000
);
}
catch
(InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
synchronized
(c) {
synchronized
(a) {
}
}
}
}
};
六、使用wait()和notify()进行线程交互
this.wait();表示让占有this的线程等待,并临时释放占有
this.notify();表示通知那些等待在this的线程,可以苏醒过来了
wait()的意思是: 让占用了这个同步对象的线程,临时释放当前的占用,并且等待。 所以调用wait是有前提条件的,一定是在synchronized块里,否则就会出错。
notify() 的意思是,通知一个等待在这个同步对象上的线程,你可以苏醒过来了,有机会重新占用当前对象了。
notifyAll() 的意思是,通知所有的等待在这个同步对象上的线程,你们可以苏醒过来了,有机会重新占用当前对象了。
七、lock
总结Lock和synchronized的区别
1. Lock是一个接口,而synchronized是Java中的关键字,synchronized是内置的语言实现,Lock是代码层面的实现。
2. Lock可以选择性的获取锁,如果一段时间获取不到,可以放弃。synchronized不行,会一根筋一直获取下去。 借助Lock的这个特性,就能够规避死锁,synchronized必须通过谨慎和良好的设计,才能减少死锁的发生。
3. synchronized在发生异常和同步块结束的时候,会自动释放锁。而Lock必须手动释放, 所以如果忘记了释放锁,一样会造成死锁。
Lock lock = new ReentrantLock();
原子操作:
例子:AtomicInteger
自增:decrementAndGet();
自减:incrementAndGet();