进程和线程的区别
进程是资源分配的最小单位,线程是CPU调度的最小单位
线程不能看做独立应用,而进程可以
进程有独立的地址空间,互相不影响,线程只是进程的不同执行路径
线程没有独立的地址空间,多进程的程序比多线程程序健壮
进程的切换比线程的切换开销大
Start和run的区别
Start()会创建一个新的子线程并启动
Run()只是Thread的一个普通方法的调用
Thread和Runnable关系
Thread是实现了Runnable接口的类,使得run支持多线程
因类的单一继承原则,推荐多使用Runnable接口
如何给run()方法传参
构造函数传参
成员变量传参
回调函数传参
如何实现处理线程的返回值
主线程等待法(新建一个属性来存返回值,当这个属性还没值的时候,就等待,直到它有值)
使用Thread类的join()阻塞当前线程以等待子线程处理完毕
通过Callable接口实现,通过FutureTask 或线程池获取(推荐)
Sleep和wait区别
Sleep是Thread类的方法,wait是Object类的方法
Sleep方法可以在任何地方使用
Wait方法只能在synchronized方法或synchronized块中使用
Thread.sleep只会让出CPU,不会导致锁行为的改变
Object.wait不仅让出CPU,还会释放已经占有的同步资源锁
1 public class ThreadTest { 2 public static void main(String[] args) { 3 final Object lock = new Object(); 4 new Thread(new Runnable() { 5 @Override 6 public void run() { 7 System.out.println("A is waiting to get lock"); 8 synchronized (lock) { 9 try { 10 System.out.println("A get lock"); 11 Thread.sleep(20); 12 System.out.println("A get do wait method"); 13 Thread.sleep(1000);//只会让出CPU,不会导致锁行为的改变 14 System.out.println("A is done"); 15 } catch (InterruptedException e) { 16 e.printStackTrace(); 17 } 18 } 19 } 20 }).start();; 21 try { 22 Thread.sleep(10);// 让A先执行 23 } catch (InterruptedException e1) { 24 e1.printStackTrace(); 25 } 26 new Thread(new Runnable() { 27 @Override 28 public void run() { 29 System.out.println("B is waiting to get lock"); 30 synchronized (lock) { 31 try { 32 System.out.println("B get lock"); 33 System.out.println("B is sleeping 10 ms"); 34 lock.wait(10);//不仅让出CPU,还会释放已经占有的同步资源锁 35 System.out.println("B is done"); 36 } catch (InterruptedException e) { 37 e.printStackTrace(); 38 } 39 } 40 } 41 }).start();; 42 } 43 }
等待池
假设线程A调用了某个对象的wait()方法,线程A就会释放该对象的锁,同时线程A就进入到了该对象的等待池中,进入到等待池中的线程不会去竞争该对象的锁
Notify和notifyAll区别
notifyAll会让所有处于等待池的线程全部进入锁池去竞争获取锁的机会
notify只会随机选取一个处于等待池中的线程进入锁池去竞争获取锁的机会
yield
当调用Thread.yield()函数时,会给线程调度器一个当前线程愿意让出CPU使用的暗示,但是线程调度器可能会忽略这个暗示
Interrupt
如果线程处于被阻塞状态,那么线程将立即退出被阻塞状态,并抛出一个InterruptedException异常。
如果线程处于正常活动状态,那么会将该线程的中断标志设为true,被设置中断标志的线程将继续正常运行,不收影响。