上次说了实现多线程的两种方式
今天来了解一下线程中的方法
多线程里面的方法
获取名字和设置名字
1)获取名字
通过getName()方法获取线程对象的名字
默认是0、1、2...这样来给线程命名的~
2)设置名字
a.通过构造函数可以传入 String 类型的名字
b.通过 setName() 方法来设置线程名称
获取当前线程的对象
通过 Thread.currentThread() 方法获取线程的对象
主线程也可以获取
休眠线程
Thread.sleep(毫秒,纳秒), 控制当前线程休眠若干毫秒,
1秒= 1000毫秒 ,1秒 = 1000 * 1000 * 1000纳秒
守护线程
setDaemon()
设置一个线程为守护线程, 该线程不会单独执行, 当其他非守护线程都执行结束后, 自动退出。
就好像我们玩游戏的时候,英雄就是守护水晶塔的,当把水晶推掉的时候,游戏就结束了,英雄的守护任务就结束了,不动了~
下面我们用代码来演示一下
t2 是守护线程,在 t1 线程结束之后,没有立即结束,还运行了一段~这个原因就是一个时间的缓冲, t2线程 收到 t1线程 结束的信息需要一定的时间,这段时间 t2就会运行一段时间。
等待线程
join()
当前线程暂停, 等待指定的线程执行结束后, 当前线程再继续
join(int)
当前线程暂停,等待指定的毫秒数之后,当前线程会继续运行
礼让线程
yield()
让出cpu~
这个方法的效果不是明显:
就比如我们一群人去抢票,我抢到了票(cpu),然后我礼让一下,执行yield()方法,把票让出去~然后还是大家一起来抢票,这一次就可能还是我抢到了票。但是我已经执行了一次礼让的操作了~
设置线程的优先级
setPriority()
设置线程的优先级
同步代码块
1)什么情况下需要同步?
当多线程并发, 有多段代码同时执行时, 我们希望某一段代码执行的过程中CPU不要切换到其他线程工作. 这时就需要同步.
如果两段代码是同步的, 那么同一时间只能执行一段, 在一段代码没执行结束之前, 不会执行另外一段代码.
2)同步代码块
使用synchronized关键字加上一个锁对象来定义一段代码, 这就叫同步代码块
多个同步代码块如果使用相同的锁对象, 那么他们就是同步的
造成这个问题的原因就是线程1没有执行完,线程2就把资源抢过去了~
现在我们来给资源加锁,注意:
锁对象可以是任意对象,但是被锁的代码需要保证是同一把锁,不能用匿名对象
同步方法
使用synchronized关键字修饰一个方法, 该方法中所有的代码都是同步的
非静态同步方法的锁是:this
这段代码用来验证
非静态的同步方法的锁对象是this
静态的同步函数的锁是:字节码对象
这段代码用来验证
非静态的同步方法的锁对象是字节码对象
线程安全问题
多线程并发操作同一数据时, 就有可能出现线程安全问题。使用同步技术可以解决这种问题, 把操作数据的代码进行同步, 不要多个线程一起操作。
模拟火车站卖票的线程
一张票被卖了四次显然是不对的
下面我们用来修改上面的代码:
1)给总票数100添加一个static,表示100张票所有线程对象共享的资源。
2)当多线程一起协作修改同一个数据(ticket)时要使用同步锁。
用实现Runnable接口的方式实现上面的卖票例子
1)这里面的ticket就不用加static,因为我们只有一个线程对象,实现了资源共享。
2)这里面的锁对象用this和字节码对象都是可以的
死锁
多线程同步的时候, 如果同步代码嵌套, 使用相同锁, 就有可能出现死锁
尽量不要嵌套使用
这样就是陷入死锁了
回顾有关线程安全的问题
咱们之前有说过一些方法的区别,是在于线程安全的问题上,我们来回顾一下:
StringBuffer是线程安全的
StringBuilder是线程不安全的
Vector是线程安全的
ArrayList是线程不安全的
Hashtable是线程安全的
HashMap是线程不安全的
没想起来的记得回去看看哦~
那么今天就分享这些了
伙伴们再见了
扩展阅读