---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------
多线程的概念
1. 线程与进程的关系
进程:指系统中正在运行的一个应用程序的实例,包括代码加载、执行和执行完毕这么一个生命周期。如打开的 播放器、打开的浏览器,我们的使用的eclipse。
线程:比进程更小的执行单位,它是在进程的基础上进一步划分的。每个进程至少包括一个线程,每次只能有一条线程获得cpu的执行权。当一个进程包含了多个线程的时候,称为多线程,Cpu需要不停地在不同线程中切换执行。
2. 多线程的优点
优点:多线程机制可以合理利用资源,解决程序中多部分同时运行的问题。如在解决多窗口售票、生产者消费者、存取款等问题时显得很有优势。
各任务需要外部数据或资源时(在有资源输入时线程才占用资源)适合使用多线程。
多线程的应用
多线程的创建有两种
方法一:继承Thread类
a. 声明一个继承Thread的子类
b. 覆盖Thread中的run方法
c. 直接创建这个子类的对象
d. 调用start方法开启线程,start后线程会自动调用run方法。
方法二:实现Runnable的类作为参数传入Thread中
a. 声明一个类实现Runnable接口
b. 覆盖接口中的run方法
c. New一个Thread, 并把Runnable的实现类传入
d. 调用Thread的start方法开启线程
第二种方法比较常用,因为使用Runnable的实现一是避免了单继承的局限性,二是适合多个具有相同代码的线程处理同一资源。
多线程的安全问题
如之前在单例设计模式中提到的懒汉式,在多线程中容易发生安全问题。多条线程在操作共享数据时容易产生。
Java中采用同步代码块或同步函数来解决多线程的问题。
同步代码块
sychronized( 对象)
{
需要被同步的代码
}
注意:
其中的对象可以是任意的,但一个对象对应一把锁。多线程判定时必须为同一把锁,否则将失去意义。
同步函数
Sychronized作为修饰符限定一个函数,表示运行这个函数的同步的。如
Sychronized void run( )
{
}
注意:
同步函数的锁是this
静态同步函数的锁是class对象
JDK1.5之后,出现了Lock类取代synchronized。创建Lock对象,通过lock方法和unlock方法实现同步。
同线程的死锁问题
当一个同步线程嵌套在另一个同步线程时发生的,由于互相拿了对方将要运行代码的锁,而导致双方都无法运行的情况。
如何避免死锁呢?将线程始终按指定的顺序来获取锁,即可以避免。
多线程中的等待唤醒机制
如输入输出问题中,如果需要输入一个就打印一个,可以设置两个线程。a负责输入,b负责输出。如何实现a在b执行一次后再执行,就要用到等待唤醒机制。
wait():将线程等待,释放了CPU执行权,同时将线程对象存储到线程池中。
notify():唤醒线程池中一个等待的线程,若线程池有多个等待的线程,则任意唤醒一个。
notifyAll():唤醒线程池中,所有的等待中的线程。
Sleep(时间):线程等待指定时长。
这三个方法都要使用在同步中,因为要对持有锁的线程进行操作。
比如,A锁上的线程被wait了,那么这个线程就进入了A锁的线程池中,只能被A锁的notify唤醒,而不能被不同锁的其他线程唤醒。
所以这三个方法要使用在同步中,因为只有同步才具有锁。
而锁可以是任意对象,这三个方法被锁调用,所以这三个方法可以被任意对象调用,所以这三个方法定义在Object类中。
wait()和sleep()的区别:
wait():可以指定等待的时间,也可以不指定时间,如果不指定时间,就只能被同一个锁的notify或notifyAll唤醒。wait时线程会释放CPU执行权,并且会释放锁。
sleep():必须指定线程休眠的时间,线程休眠即暂停执行。时间到了,线程就自动苏醒,恢复运行。sleep时线程会释放执行权,但不释放锁。
---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------