2、如何创建一个线程:
1.实现Runnable接口,然后将它传递给Thread的构造函数,创建一个Thread对象
public class DisplayMessage implements Runnable { public void run() {//重写run方法 } }
Runnable hello = new DisplayMessage("Hello");
Thread thread1 = new Thread(hello);
thread1.start(); //启动线程
2.直接继承Thread类。
public class GuessANumber extends Thread{public void run() {}}
Thread thread3 = new GuessANumber(27);
thread1.start();
3、线程的生命周期
当我们在java程序中新建一个线程时,状态是new。调用线程start()方法时。状态为Runnable。
线程调度器为Runnable线程池中的线程分配CPU时间并且将它们的状态改变为Running。其他还有
线程时间片用完,IO请求或者线程中断或打断会造成阻塞 waiting,Blocked 和Dead。
4、线程之间如何通信的?
wait() notify() notifyAll()方法可以用于线程间通信关于锁的状态
5、wait() notify()和notifyAll()必须在同步方法或者同步块中被调用
6、如何确保线程安全,也就是线程同步?
使用原子类,实现并发锁,使用volatile关键字,使用不变类和线程安全类
7、同步方法和同步块,哪个更好?
同步块是更好的选择,因为它不会锁住整个对象。同步方法会锁住整个对象,哪怕这个类中有多
个不相关的同步块,这通常会导致他们停止执行并需要等待获得这个对象的锁
8、什么是死锁?如何分析和避免死锁?
死锁是指两个以上的线程永远阻塞的情况,这种情况产生至少需要两个以上的线程和两个以上的资源。
所有线程都在等待共享资源的释放
分析死锁,我们需要查看java应用程序的线程转储。需要找出那些状态为BLOCKED的线程和他们等待的
资源。每个资源都有一个唯一的id,用这个id我们可以找出哪些线程已经拥有了它的对象锁。
避免嵌套锁,只在需要的地方使用锁和避免无限期等待是避免死锁的通常方法。
9、什么是线程池?如何创建一个java线程池?
一个线程池管理了一组工作线程,同时它还包括了一个用于放置等待执行的任务的队列。
java.util.concurrent.Executors提供了一个java.util.concurrent.Executor接口的实现用于创建线程池。
10、sleep()和yield()的区别
1.sleep() 使当前线程进入停滞状态,所以执行sleep()的线程在指定的时间内肯定不会执行,同时
sleep函数不会释放锁资源
sleep 可使优先级低的线程得到执行的机会,当然也可以让同优先级和高优先级的有执行机会
2.yield() 只是使当前线程重新回到可执行状态,有可能在进入可执行状态后马上又被执行,只能使
同优先级的线程有执行的机会。同样不会释放锁资源
所以,sleep和yield的区别在于,
1.sleep可以使优先级低的得到执行的机会,而yield只能使同优先级的
线程有执行的机会。
2.sleep()方法会将线程转入阻塞状态,直到阻塞时间结束,才会转入就绪状态。
yield()方法会将当前线程直接转入就绪状态。
3.sleep()方法声明抛出了InterruptedException异常,所以调用sleep()方法时要么捕捉该异常,要么显示声明抛出该异常。
yield()方法则没有声明抛出任何异常。
4.sleep()方法比yield()方法有更好的移植性,通常不建议使用yield()方法来控制并发线程的执行。