极力推荐文章:欢迎收藏
和您一起终身学习,这里是程序员Android
1、开启线程的三种方式?
1)继承Thread
类,重写run()
方法,在run()
方法体中编写要完成的任务 new Thread().start();
2)实现Runnable
接口,实现run()
方法 new Thread(new MyRunnable()).start();
3)实现Callable
接口MyCallable
类,实现call()
方法,使用FutureTask
类来包装Callable
对象,使用FutureTask
对象作为Thread
对象的target
创建并启动线程;调用FutureTask
对象的get()
方法来获得子线程执行结束后的返回值。
FutureTask<Integer> ft = new FutureTask<Integer>(new MyCallable());
new Thread(ft).start();
2、run()和start()方法区别
run()
方法只是线程的主体方法,和普通方法一样,不会创建新的线程。
只有调用start()
方法,才会启动一个新的线程,新线程才会调用run()
方法,线程才会开始执行。
3、如何控制某个方法允许并发访问线程的个数?
创建Semaphore
变量,Semaphore semaphore = new Semaphore(5, true);
当方法进入时,请求一个信号,如果信号被用完则等待,方法运行完,释放一个信号,释放的信号新的线程就可以使用。
4、在Java中wait和seelp方法的不同
wait()
方法属于Object
类,调用该方法时,线程会放弃对象锁,只有该对象调用notify()
方法后本线程才进入对象锁定池准备获取对象锁进入运行状态。
sleep()
方法属于Thread
类,sleep()
导致程序暂停执行指定的时间,让出CPU
,但它的监控状态依然保存着,当指定时间到了又会回到运行状态,sleep()
方法中线程不会释放对象锁。
5、谈谈wait/notify关键字的理解
notify:
唤醒在此对象监视器上等待的单个线程
notifyAll():
通知所有等待该竞争资源的线程
wait:
释放obj
的锁,导致当前的线程等待,直接其他线程调用此对象的notify()
或notifyAll()
方法
当要调用wait()
或notify()/notifyAll()
方法时,一定要对竞争资源进行加锁,一般放到synchronized(obj)
代码中。当调用obj.notify/notifyAll
后,调用线程依旧持有obj
锁,因此等待线程虽被唤醒,但仍无法获得obj
锁,直到调用线程退出synchronized
块,释放obj
锁后,其他等待线程才有机会获得锁继续执行。
6、什么导致线程阻塞?
(1)一般线程阻塞
1)线程执行了Thread.sleep(int millsecond)
方法,放弃CPU
,睡眠一段时间,一段时间过后恢复执行;
2)线程执行一段同步代码,但无法获得相关的同步锁,只能进入阻塞状态,等到获取到同步锁,才能恢复执行;
3)线程执行了一个对象的wait()
方法,直接进入阻塞态,等待其他线程执行notify()/notifyAll()
操作;
4)线程执行某些IO
操作,因为等待相关资源而进入了阻塞态,如System.in
,但没有收到键盘的输入,则进入阻塞态。
5)线程礼让,Thread.yield()
方法,暂停当前正在执行的线程对象,把执行机会让给相同或更高优先级的线程,但并不会使线程进入阻塞态,线程仍处于可执行态,随时可能再次分得CPU
时间。线程自闭,join()
方法,在当前线程调用另一个线程的join()
方法,则当前线程进入阻塞态,直到另一个线程运行结束,当前线程再由阻塞转为就绪态。
6)线程执行suspend()
使线程进入阻塞态,必须resume()
方法被调用,才能使线程重新进入可执行状态。
7、线程如何关闭?
1) 使用标志位
2)使用stop()
方法,但该方法就像关掉电脑电源一样,可能会发生预料不到的问题
3)使用中断interrupt()
public class Thread {
// 中断当前线程
public void interrupt();
// 判断当前线程是否被中断
public boolen isInterrupt();
// 清除当前线程的中断状态,并返回之前的值
public static boolen interrupted