主要还是熟悉api,熟悉方法,简单,需要多实践
1、 多线程实现方法和区别:
- 多线程实现的两种方法:
1)类继承Thread类或实现Runnable接口,重写run()方法
2)创建Thread的子类对象(需要开几个线程就创建几个对象,可创建匿名内部类)
3)子类对象.start()或者将实现了Runnable接口的对象当作参数放到Thread构造方法里再子类对象.start()
也可以采用匿名类的方法重写Thread里面的run()方法,将我们要执行的语句写到run()方法里面,然后直接.start()
多线程的要执行的代码主要就是写在重写的run方法里,子类如果重写了run,那就调用子类的run,如下,如果采用匿名类,因为编译看父类,运行看子类,如果子类没有重写run,那就直接用父类重写过的run
Thread的run源码,如果子类不为空,就调用子类的run:
public void run() {
if (target != null) {
target.run();
}
}
(继承Thread类如果需要在几个线程里面共享的数据,比如,1000张票,四个窗口卖,这个票需要变成静态的,就是在类加载的同时加载进方法区的静态区,由线程所共享,但是实现Runnable接口就不需要了,因为只创建了一个类,然后用thread的构造方法创建四个线程一起运行这个类)
2. 两种方法源码的区别:
1)继承Thread:由于子类重写了Thread的run(),当调用start()的时候,直接找子类的run()方法
2)实现Runnable:构造函数中传入了Runnable的引用,成员变量记住了它,start()调用run()方法时内部判断成员变量Runnable的引用是否为空,不为空的时候编译看的是Runnable的run(),运行时执行的是子类的run()方法
3. 写代码时的区别
1) 继承Thread:好处是可以直接使用Thread类中的方法,代码简单,弊端是如果已经有了父类,就不能用这种方法(Java中每个类都只能继承一个类,但可以实现多个接口)
2)实现Runnable:好处是即使自己定义的线程类有了父类也没关系,可以实现多个接口;弊端是不能直接使用Thread中的方法需要
2、同步代码块和方法:
将代码块或者方法用锁对象锁起来,这样在完整低执行了一次代码块或者方法后CPU才会切换线程(也就是说,线程之间不干扰,是线程安全的)
synchronized(锁对象){方法}: 同步代码块,锁机制,锁对象可以是任意的,但是锁只能是相同的类(匿名类就不行),如果用引用数据类型变量(比如自己创建的对象)当作锁对象,必须是静态的,static
synchronized 方法(){}: 非静态同步方法,直接用关键字修饰方法,其锁对象是this
static synchronized 方法(){}: 静态同步方法,直接用关键字修饰方法,其锁对象是字节码对象(就像是创建了同步代码块然后把锁对象当作参数放到小括号里)
注意:嵌套同步代码块会造成死锁,最好不要嵌套