线程笔记
同步锁
- 保证数据操作的完整性
- 每个对象对应一个锁的标记,保证在任一时刻,只能有一个线程访问该对象
- 用synchronized修饰符来与对象的同步锁联系
- 加同步锁会导致程序的执行效率降低
- 非静态同步方法的锁为this(当前对象),静态同步方法的锁为当前类本身
创建线程的方式
- 实现Runnable接口
public class test_03{
public static void main(String[] args) {
ThreadTest test = new ThreadTest();
Thread t = new Thread(test);
t.start();
}
}
class ThreadTest implements Runnable{
<span class="hljs-meta">@Override
<span class="hljs-function"><span class="hljs-keyword">public <span class="hljs-keyword">void <span class="hljs-title">run<span class="hljs-params">() {
System.out.println(<span class="hljs-string">"创建了一个线程:"+Thread.currentThread().getName());
}
}
2. 继承Thread类
public class test_03{
public static void main(String[] args) {
ThreadTest test = new ThreadTest();
test.start();
}
}
class ThreadTest extends Thread{
@Override
public void run() {
System.out.println("创建了一个线程:"+Thread.currentThread().getName());
}
}
推荐使用实现Runnable接口的方式来创建线程,原因如下
- 不需要重写Thread类的方法
- 可以弥补java单继承的机制
- 多个线程可以共享一个Runnable实例对象
- 使用接口更灵活
线程常用的方法
- setName -> 设置线程名
- getName -> 返回线程名
- start -> 执行线程
- run -> 线程对象的主方法,(是一个普通方法,直接调用不会创建线程)
- setPriority -> 更改线程的优先级
- getPriority -> 获取线程的优先级
- sleep -> 休眠、暂停执行 (毫秒)
- interrupt -> 中断线程,(如果一个线程处于了阻塞状态,则会抛出InterruptedException异常,为了让线程从阻塞状态醒来,并且在结束线程前让程序员有足够的时间来处理中断请求)
- yield -> 线程礼让,礼让的时间不确定,不一定会礼让成功(资源紧张时成功的概率高,由CPU决定)
- join -> 让其他线程插队,执行完插队的线程任务,再继续执行当前线程
举例
public class test_02 {
public static void main(String[] args) {
ThreadDemo demo = new ThreadDemo();
Thread t = new Thread(demo);
t.setName("凣凣");
//设置优先级为1 默认为5 最大为10
t.setPriority(Thread.MIN_PRIORITY);
t.start();
Thread.currentThread().setName("主线程");
for (int i = 1; i<=5;i++){
System.out.println(Thread.currentThread().getName() + "吃饭中...");
try {
//休眠0.5秒
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//中断线程
t.interrupt();
}
}
class ThreadDemo implements Runnable{
@Override
public void run() {
while (true){
System.out.println(Thread.currentThread().getName() + "等吃完饭去睡觉...");
try {
//休眠20秒
Thread.sleep(20000);
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName() + "吃完饭了,我要去睡觉zzZ");
return;
}
}
}
}
打印执行结果
线程分类
- 用户线程:也叫工作线程,当线程任务执行完或以通知方式结束
- 守护线程:可以理解为为工作线程服务的线程,当所有的用户线程结束,守护线程自动结束
public class test_02 {
public static void main(String[] args) {
ThreadDemo demo = new ThreadDemo();
Thread t = new Thread(demo);
//调用Thread对象的setDaemon(true)将线程设为守护线程
t.setDaemon(true);
t.start();
for (int i = 1; i<=10;i++){
System.out.println("吃饭中...");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class ThreadDemo implements Runnable{
@Override
public void run() {
while (true){
System.out.println("等吃完饭去睡觉...");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
- 执行结果
打印执行结果
死锁
- 多个线程占用了对方的锁资源无法释放导致死锁
示例
//模拟线程死锁
public class test_01 {
public static void main(String[] args) throws IOException, InterruptedException {
Thread t1 = new Thread(new LockDemo(true));
Thread t2 = new Thread(new LockDemo(false));
t1.setName("第一个线程");
t2.setName("第二个线程");
t1.start();
t2.start();
}
}
class LockDemo implements Runnable{
static Object o1 = new Object();
static Object o2 = new Object();
boolean flag;
<span class="hljs-function"><span class="hljs-keyword">public <span class="hljs-title">LockDemo<span class="hljs-params">(<span class="hljs-keyword">boolean flag){
<span class="hljs-keyword">this.flag = flag;
}
<span class="hljs-comment">//死锁
<span class="hljs-function"><span class="hljs-keyword">public <span class="hljs-keyword">void <span class="hljs-title">run<span class="hljs-params">(){
<span class="hljs-keyword">if(flag){
<span class="hljs-comment">//第一个线程会拿到o1的锁
<span class="hljs-keyword">synchronized (o1){
System.out.println(Thread.currentThread().getName()+<span class="hljs-string">"得到锁1");
<span class="hljs-comment">//当想去拿o2的锁时,拿不到,因为已经被第二个线程占用
<span class="hljs-keyword">synchronized (o2){
System.out.println(Thread.currentThread().getName()+<span class="hljs-string">"得到锁2");
}
}
}<span class="hljs-keyword">else{
<span class="hljs-comment">//第二个线程会拿到o2的锁
<span class="hljs-keyword">synchronized (o2){
System.out.println(Thread.currentThread().getName()+<span class="hljs-string">"得到锁2");
<span class="hljs-comment">//当想去拿o1的锁时,拿不到,因为已经被第一个线程占用
<span class="hljs-keyword">synchronized (o1){
System.out.println(Thread.currentThread().getName()+<span class="hljs-string">"得到锁1");
}
}
}
}
}
执行上述代码,程序卡住不动,也没有结束进程。形成死锁
线程生命周期
- NEW -> 创建
- Runnable -> 可运行
- Ready -> 就绪
- Running -> 运行
- TimedWaiting -> 及时等待
- Waiting -> 等待
- Blocked -> 阻塞
- Terminated -> 已退出
线程生命周期图
END

浙公网安备 33010602011771号