------- android培训、java培训、期待与您交流! ----------
线程的定义
进程:当前正在执行的程序,代表一个应用程序在内存中的执行区域。
线程:是进程中的一个执行控制单元,执行路径。
一个进程中如果只有一个执行路径,这个程序称为单线程。
一个进程中有多个执行路径时,这个程序成为多线程。
多线程的好处:它的出现可以同时执行多条路径,让多部分代码同时执行,提高了效率
jvm启动不止一个线程,除了主线程,还有负责垃圾回收机制打的线程
创建线程
1,继承Thread
定义类继承Thread
重写run方法(Thread类中的run方法用于存储线程要运行的代码)
把新线程要做的事写在run方法中
创建线程对象
开启新线程,调用start()方法,程序内部会自动执行run方法
Thread类常用方法
1,设置名字
通过构造函数可以传入String类型的名字super(String);
通过setName(String)方法可以设置线程对象的名字
2,获取名字
通过getName()方法获取线程对象的名字
3,获取当前线程对象
Thread.currentThread(),主线程也可以获取
4,休眠
Thread.sleep(毫秒), 控制当前线程休眠若干毫秒1秒= 1000毫秒
5,守护
setDaemon(),该方法在启动前调用。设置一个线程为守护线程,该线程不会单独执行,当其他非守护线程都执行结束后,自动退出
6,加入
join(), 主线程暂停, 等待使用join方法的线程执行结束后,主线程再继续
join(int), 可以等待指定的毫秒之后继续
7,yield停止当前线程,运行其他线程
2,实现Runnable
定义类实现Runnable接口
创建run方法
把新线程要运行的代码存放在run方法中
创建自定义的Runnable对象
创建Thread对象,传入Runnable接口的子类对象
调用start()开启新线程, 内部会自动调用Runnable的run()方法
两种方式的区别
区别一:
由于子类重写了Thread类的run(), 当调用start()时, 直接找子类的run()方法
构造函数中传入了Runnable的引用, 成员变量记住了它, start()调用run()方法时内部判断成员变量Runnable是否为空, 不为空则执行Runnable的run()
区别二:
继承Thread只能是单继承,如果自己定义的线程类已经有了父类,就不能再继承了
实现Runnable接口可以多实现,即使自己定义线程类已经有父类可以实现Runnable接口
继承Thread的好处是:可以直接使用Thread类中的方法,代码简单
弊端是:如果已经有了父类,就不能用这种方法
实现Runnable接口的好处是:即使自己定义的线程类有了父类也没关系,因为有了父类也可以实现接口。而且接口是可以多实现的
弊端是:不能直接使用Thread中的方法。需要先获取到线程对象后,才能得到Thread的方法,代码复杂
wait()和sleep()有什么区别?
对时间的指定。
1,sleep方法必须指定时间。
2,wait方法有重载形式,可以指定时间,也可以不指定时间。
对于执行权和锁的操作.
1,sleep():释放执行权,不释放锁,因为肯定能醒,肯定可以恢复到临时阻塞状态。
2,wait():释放执行权,释放锁。
线程之间的同步
当多线程并发,有多段代码同时执行时, 我们希望某一段代码执行的过程中CPU不要切换到其他线程工作,这时就需要同步
如果两段代码是同步的,那么同一时间只能执行一段,在一段代码没执行结束之前,不会执行另外一段代码。
同步代码块
格式:
synchronized(对象)
{//该对象可以是任意对象
需要同步的代码;
}
同步中执行同步可以解决安全问题的根本原因就在那个对象上,对象如同锁的功能,持有锁的线程可以执行(例子:火车卫生间)
同步的特点:
同步的前提:
同步需要两个或者两个以上的线程。
多个线程使用的是同一个锁。
未满足这两个条件,不能称其为同步。
同步的好处:
同步的出现解决了多线程的安全问题。
同步的弊端:
当线程相当多时,因为每个线程都会去判断同步上的锁,这是很耗费资源的,无形中会降低程序的运行效率
同步函数
使用synchronized关键字修饰一个方法。该函数中所有的代码都是同步的
非静态同步方法默认使用当前对象this作为锁对象
静态同步函数的锁
静态函数使用的锁肯定不是this,因为静态函数中不可以定义this
静态随着类的加载而加载,这时有可能内容还没有该类的对象,但是一个类加载进内存,会先将这个类对应的字节码文件封装成对象,该对象的表示方式:类名.class
线程之间的通信
如果希望线程等待,就调用wait()
如果希望唤醒等待的线程,就调用notify();
这两个方法必须在同步代码中执行, 并且使用同步锁对象来调用
多个线程通信的问题
notify()方法是随机唤醒一个线程(优先唤醒先等待的线程)
notifyAll()方法是唤醒所有线程
JDK1.5之前无法唤醒指定的一个线程
如果多个线程之间通信, 需要使用notifyAll()通知所有线程, 用while来反复判断条件
1.5中提供了多线程升级解决方案:
将同步Synchronized替换成现实Lock操作,
将object中wait,notify,notifyAll替换成了Condition对象
该对象可以通过Lock锁进行获取 lock.newCondition()
停止线程:
run方法结束,只有控制循环,就可以让run方法结束。
特殊情况:
当线程处于冻结状态,就不会读取到标记,线程不会结束。
当没有指定的方发让冻结的线程恢复到运行状态时,这时需要对冻结进行清除
强制让线程恢复到运行状态中,这样就可以操作标记让线程结束
Thread类提供该方法 interrupt()