多线程

一、

设计一个类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();

原文地址:https://www.cnblogs.com/zxj-262410/p/8492806.html