现在的位置: 首页 > 综合 > 正文

黑马程序员—–线程学习

2018年01月11日 ⁄ 综合 ⁄ 共 2168字 ⁄ 字号 评论关闭

-------
android培训
java培训、期待与您交流! ----------

线程的学习

1.多线程的安全问题
问题原因:
当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,另一个线程参与进来执行。导致共享数据的错误。
解决办法:
对多条操作共享数据的语句,只能让一个线程都执行完。在执行过程中,其他线程不可以参与执行。
Java对于多线程的安全问题提供了专业的解决方式。
就是同步代码块。
synchronized(对象)
{
 需要被同步的代码;
}
同步函数:用同步关键字修饰的函数。同步函数的锁是this。
同步的前提:
1,必须要有两个或两个以上的线程。
2,必须是多个线程使用同一个锁。

静态的同步方法,使用的锁是该方法所在类的字节码文件对象。类名.class属于Class类的对象。

wait();
notify();
notifyAll();
都使用在同步中,因为要对持有监视器(锁)的线程操作。
所以要使用在同步中,因为只有同步才具有锁。

为什么这些操作线程的方法要定义在Object类中呢?
因为这些方法在操作同步中线程时,都必须要标识它们所操作的线程持有的锁,只有同一个锁上的被等待线程,可以被同一个锁上notify唤醒。不可以对不同锁中的线程进行唤醒。

也就是说,等待和唤醒必须是同一个锁。
 而锁可以是任意对象,所以可以被任意对象调用的方法定义在Object类中。

对于多个生产者和消费者。12-5
为什么要定义while判断标记。
原因:让被唤醒的线程再一次判断标记。

为什么定义notifyAll,
因为需要唤醒对方线程。
因为如果只用notify,容易出现只唤醒本方线程的情况,导致程序中的所有线程都等待。

jdk1.5中提供了多线程升级解决方案。
将同步Synchronized替换成现实Lock操作。
将Object中的wait、notify、notifyAll替换成了Condition对象。
该对象可以Lock锁进行获取。
例子:作为一个示例,假定有一个绑定的缓冲区,它支持 put 和 take 方法。如果试图在空的缓冲区上执行 take 操作,则在某一个项变得可用之前,线程将一直阻塞;如果试图在满的缓冲区上执行 put 操作,则在有空间变得可用之前,线程将一直阻塞。我们喜欢在单独的等待 set 中保存 put 线程和 take 线程,这样就可以在缓冲区中的项或空间变得可用时利用最佳规划,一次只通知一个线程。可以使用两个 Condition 实例来做到这一点。

 class BoundedBuffer {
   final Lock lock = new ReentrantLock();
   final Condition notFull  = lock.newCondition();
   final Condition notEmpty = lock.newCondition();

   final Object[] items = new Object[100];
   int putptr, takeptr, count;

   public void put(Object x) throws InterruptedException {
     lock.lock();
     try {
       while (count == items.length)
         notFull.await();
       items[putptr] = x;
       if (++putptr == items.length) putptr = 0;
       ++count;
       notEmpty.signal();
     } finally {
       lock.unlock();
     }
   }

   public Object take() throws InterruptedException {
     lock.lock();
     try {
       while (count == 0)
         notEmpty.await();
       Object x = items[takeptr];
       if (++takeptr == items.length) takeptr = 0;
       --count;
       notFull.signal();
       return x;
     } finally {
       lock.unlock();
     }
   }
 }

stop方法已经过时。
如何停止线程?
只有一种:run方法结束。
只要控制住循环,就可以让run方法结束,也就是线程结束。

特殊情况:同步+wait   12-7
当线程处于了冻结状态,就不会读取到标记。那么线程就不会结束。
当没有指定的方式让冻结的线程恢复到运行状态时,这时需要对冻结进行清除。强制让线程恢复到运行状态中来。这样就可以操作标记让线程结束。

Thread类提供该方法 interrupt();

public final void setDaemon(boolean on)
将该线程标记为守护线程或用户线程。当正在运行的线程都是守护线程时,JVM退出。该方法必须在启动线程前调用。

public final void join()throws InterruptedException
等待该线程终止。
当A线程执行到了B线程的join()方法时,A就会等待。等B线程都执行完,A才会执行。

 

抱歉!评论已关闭.