java使用多线程的方法
1.extends Thread类
2.implements Runnable接口
二者区别:
Thread实现了Runnable接口。
java不支持多重继承,故采用继承Thread类的方法就不能再继承其它类了,但是实现Runnable接口的话还可以实现其它接口。
sleep()和wait()的区别
1.sleep()属于Thread,wait()属于Object
2.sleep()不会释放锁,wait()会释放锁
3.sleep()要设置时间,wait()不需要,可以用notify()唤醒
start()和run()的区别
使用run()不会启动多个线程,必须使用start()方法synchronized
多线程的同步机制对资源加锁,使得只有一个线程可以操作用法:
1. 修饰一个方法,这个方法就叫做同步方法。
class T extends Thread { PRivate int id; public T(int v) { id = v; } public synchronized void Print(int v) { while(true) System.out.println(v); } public void run() { Print(id); } } 2. 对一个资源加锁,synchronized(object),建议对静态变量加锁,提高效率
class T extends Thread { private int count=0; private int id; private static Object lock=new Object(); public T(int v) { id = v; } public void printV(int v) { synchronized(lock) { while(count++<=10) System.out.println(v); } } public void run() { printV(id); } } 注意:● 当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。●当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。可以这么理解,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。Join
join用于主线程等待子线程运行完毕它的run方法,再继续执行下面的代码。
public class ThreadTester { public static void main(String[] args) throws InterruptedException{ Thread t1=new Thread(new ThreadTesterA()); Thread t2=new Thread(new ThreadTesterB()); t1.start(); t1.join(); //t1线程完成run方法后才会继续执行下面的代码! t2.start(); t2.join(); } }
线程池的作用
多线程的处理方式,可以减少线程的创建和销毁次数,使线程的数量保持在一个较为合理的范围。适用情况
●需要大量的线程来完成任务,且完成任务的时间比较短。 WEB服务器完成网页请求这样的任务,使用线程池技术是非常合适的。因为单个任务小,而任务数量巨大,你可以想象一个热门网站的点击次数。 但对于长时间的任务,比如一个Telnet连接请求,线程池的优点就不明显了。因为Telnet会话时间比线程的创建时间大多了。●对性能要求苛刻的应用,比如要求服务器迅速响应客户请求。●接受突发性的大量请求,但不至于使服务器因此产生大量线程的应用。突发性大量客户请求,在没有线程池情况下,将产生大量线程,虽然理论上大部分操作系统线程数目最大值不是问题,短时间内产生大量线程可能使内存到达极限,并出现"OutOfMemory"的错误。不适用情况
●如果需要使一个任务具有特定优先级●如果具有可能会长时间运行(并因此阻塞其他任务)的任务●如果需要将线程放置到单线程单元中(线程池中的线程均处于多线程单元中)●如果需要永久标识来标识和控制线程,比如想使用专用线程来终止该线程,将其挂起或按名称发现它新闻热点
疑难解答