线程学习
两种方法创建线程,通常使用第二种方法更加灵活,主要是第二种方法适合多个相同程序的线程去处理同一资源的情况,即创建多个线程,传入同一个对象,就是对该对象同时用多个线程进行处理。
1. 创建Thread类的对象就是创建了一个线程,Thread类中的run方法是空的,通常继承Thread类,覆盖run方法:
Thread tt = new MyThread();
tt.start();//start方法启动线程,自动调用Threead里的run方法,要在线程里运行的程序写在run方法里。
2. 使用Runnable接口:Thread类中有个带参数的构造函数,参数是Runnable对象。通常实现Runnable接口,覆盖run方法。
Thread tt = new Thread(new SubRunnable());//参数中传入Runnable接口实现类的对象。
后台线程:启动之前调用tt.setDaemon(true);如果只有后台线程在运行,进程就会结束。
前台线程:默认或调用tt.setDaemon(false);前台线程没结束进程就不会结束。
多线程同步问题:多个线程轮流执行,有可能一个线程没有昨完就做第二个线程,导致结果不对。
解决方法1:把程序放在同步语句块中,只能有一个线程进来,这种性能成为原子性。
synchronized(object)//(程序变慢,因为总要判断监视器,花销变大)
{同步代码块
.......}
object称为监视器,可以是任意的对象,所有对象都有标志位,为0或1,当为1时,继续向下执行并且变为0;当为0时线程阻塞放入线程池中,直到变为1。
解决方法2:同步函数,把程序放在同步函数里,同步对象是this
public Synchronized void func()
{......
}
死锁问题
两个线程占着自己的资源锁还要申请对方资源上的锁,会导致程序停滞不前。
线程间的通信:两个线程间相互控制对方的启动和暂停的方法
1. wait(); 是当前线程等待,直到其他线程进入同一监视器并调用notify()才继续执行。
2. notify(); 唤醒同一监视器中等待着的线程
3. notifyAll(); 唤醒同一对象监视器中所有等待着的线程,具有最高优先级的线程首先被唤醒执行。
stop();suspend();停止线程,基本不用,因为容易发生死锁。
通常想要停止线程,设置一个flag,while(flag); 写一个停止自己的函数将flag改为false,在另一个线程中调用该函数即可。
线程安全类:类中的方法是线程安全的,有同步的处理。