线程的同步机制:
1.背景
例子:创建多个窗口卖票,总票数为100张,使用实现Runnable接口的方式
1.问题:买票过程中,出现了重票、错票 --> 出现了线程的安全问题
2.问题出现的原因:当某个线程 *** 作车票的过程中,尚未 *** 作完成时,其他线程参与进来,也 *** 作车票
3.如何解决:当一个线程a在 *** 作票的时候,其他线程不能参与进来。直到a *** 作完,其他线程才可以开始 *** 作。这种情况即使线程a出现了阻塞,也不能被改变
2.Java解决方案:同步机制
方式一:同步代码块
synchronized(同步监视器){
//需要被同步的代码
}
说明:
1. *** 作共享数据的代码,即为需要被同步的代码 --> 不能包含代码多了或少了
2.共享数据:多个线程共同 *** 作的变量。 比如:ticket就是共享数据
3.同步监视器,俗称锁:任何一个类的对象都可以充当锁,但是多个线程必须共用同一把锁
补充:在实现Runnable接口创建多线程的方式中,可以考虑使用this充当同步监视器。
在继承Thread类创建多线程的方式中,慎用this充当同步监视器,考虑使用当前类充当同步监视器
方式二:同步方法
如果 *** 作共享数据的代码完整的声明在一个方法中,我们不妨将此方法声明为同步的
关于同步方法的总结:
1.同步方法仍然涉及到同步监视器,只是不需要我们显式的声明
2.非静态的同步方法,同步监视器是:this
静态的同步方法,同步监视器是:当前类本身
解决线程安全问题的方式:Lock锁 --- JDK5.0新增
1.面试题:synchronized 与 Lock的异同?
相同:二者都可以解决线程安全问题
不同:synchronized机制在执行玩相应的同步代码以后,自动的释放同步监视器
Lock需要手动的启动同步(Lock(),同时结束同步也需要手动实现(unLock()
使用的优先顺序:
Lock --> 同步代码块(已经进入了方法体,分配了相应资源) --> 同步方法(在方法体之外)
3.利弊:
好处:同步的方式,解决了线程的安全问题
坏处: *** 作同步代码时,只能一个线程参与,其他线程等待,相当于是一个单线程的过程,效率低。java培训
线程通信
1.线程通信涉及到的三个方法
wait():一旦执行此方法,当前线程就进入阻塞状态,并释放同步监视器
notify():一旦执行此方法,就会唤醒被wait的一个线程。如果有多个线程被wait,就唤醒优先级高的那个
notifyAll():一旦执行此方法,就会唤醒所有被wait的线程
2.说明
1.这三个方法必须使用在同步代码块或同步方法中
2.这三个方法的调用者必须是同步代码块或同步方法中的同步监视器,否则,会出现IllegalMonitorStateExceprion异常
3.这三个方法是定义在java.lang.Object类中
3.sleep() 和 wait()的异同:
1.相同点:一旦执行方法,都可以使当前线程进入阻塞状态
2.不同点:
1.调用要求不同:sleep()可以在任何需要的场景下调用。wait()必须使用在同步代码块或同步方法中
2.关于是否释放同步监视器:sleep()不释放,wait()释放
JDK5.0新增线程创建的方式一 Callable
1.如何理解实现Callable接口的方式创建多线程比实现Runnable接口创建多线程方式强大?
1.call()可以返回值
2.call()可以抛出异常,被外面的 *** 作捕获,获得异常的信息
3.Callable是支持泛型的
JDK5.0新增线程创建的方式二 线程池
1.好处:
1.提高响应速度(减少了创建新线程的时间)
2.降低资源消耗(重复利用线程池中线程,不需要每次都创建)
3.便于线程管理
corePoolSize: 核心池的大小
maximumPoolSize: 最大线程数
keepAliveTime: 线程没任务时最多保持多长时间后会终止。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)