多线程是啥?有啥用?(上)

以前对多线程已经总结过:
【java高级】简说多线程(上)
【java高级】简说多线程(下)
现在又翻看多线程,对其理解的更系统了,现总结如下。
在这里插入图片描述

线程的操作

(1)线程的生命周期

在这里插入图片描述

  • 新建

当程序使用new关键字创建了一个线程之后,该线程就处于新建状态。此时它和其它的java对象一样,仅仅由jvm为其分配内存,并初始化其属性的值。

  • 就绪

jvm为其创建方法调用栈和程序计数器,此时的线程表示自己可以运行了,但具体什么时候运行,取决于jvm里的线程调度器的调度。

  • 运行

我们知道,cpu用于执行线程,即使有多个线程,cpu也只能一次执行一个。线程获得资源的方式有两种:共用式和抢占式。目前操作系统大多采用抢占式,因为其效率更高。
在这里插入图片描述

  • 阻塞

线程进入阻塞状态的情况:
a、调用sleep()方法主动放弃所占用的处理器资源
b、试图获得一个锁,但此时这个锁正在被其它线程所持有(synchronized、lock)
c、线程在等待某个通知(notify)
d、调用了一个阻塞式IO方法,在改方法返回前,该线程被阻塞

需要注意的是,程序从阻塞状态只能进入就绪状态,而不能进入运行状态。这个在生命周期图中也能看出来。

  • 死亡

线程就像人的生命,出生和死亡都只能有一次。当一个线程死亡后,无法再用start()方法重启它。

(2)创建和启动

线程的创建有两种方式:继承Thread类;实现Runnable接口。推荐采用后者。
线程的启动是调用start()方法。

//通过实现Runnable接口来创建线程类
public class Thread implements Runnable
{
 private int i;
 public void run(){
    for(;i<100;i++)
    { 
       sout(Thread.currentThread().getName()+""+i);
    }
  }
  public static void main(String[] args){
     for(int i=0;i<100;i++)
     {
       sout(Thread.currentThread().getName()+""+i);
       if(i==20){
          Thread t=new Thread();
          new Thread(t,"新线程1").start();
          new Thread(t,"新线程2").start();
        }
     }
  }
}

(3)线程的控制

  • join()方法

作用:让一个线程等待另一个线程执行完后再往下执行。

public class JoinThread extends Thread
{
 public Thread(String name)
 {
   super(name);
 }
 public void run(){
    for(int i=0;i<100;i++)
    { 
       sout(getName()+""+i);
    }
  }
  public static void main(String[] args) throws Exception{
    //启动子线程
    new JoinThread("新线程").start();
     for(int i=0;i<100;i++)
     {
       if(i==20){
          JoinThread jt=new JoinThread("被Join的线程");
          jt.start();
          //main线程必须等jt线程执行结束后才会向下执行
          jt.join();
        }
         sout(Thread.currentThread().getName()+""+i);
     }
  }
}
  • sleep()、yield()方法

sleep()用于让正在执行的线程暂停一段时间,并进入阻塞状态。

//让当前线程暂停1s
Thread.sleep(1000);

yield()用于让正在执行的线程暂停,进入就绪状态。和sleep()的区别是,sleep()就睡死过去了。yield()就像让线程又回到起始点,和其它线程一起竞争cpu的资源,它还是有可能竞争上的。

  • 改变优先级

每个线程执行时都有一定的优先级,优先级高的线程会获得更多的执行机会。注意,是更多的机会,更大的概率,不是肯定会竞争到资源。

//设置优先级,范围是1~10,10是优先级最高的
setPriority(int newPriority);
//返回指定线程的优先级
getPriority();
  • 后台线程

后台线程是在后台运行的,为其它线程提供服务的线程。它的特点是如果所有的前台线程都死亡,后台线程会自动死亡。jvm的垃圾回收线程就是典型的后台线程。

//设置成后台线程,需要在线程启动之前设置
setDaemon(true)
//判断线程是否为后台线程
isDaemon();
同步

让线程之间进行同步执行,可以使用锁。线程同步就像上厕所,总得一个一个来,你不起来,别人没发上。同样,当你来了发现有人在占用厕所,那你就需要等待。对应到线程上就是:
a、进厕所,锁上门——获取锁
b、解决个人问题——修改
c、解决完出门,把锁打开——释放锁
在这里插入图片描述

(1)Synchronized

//同步代码块
synchronized(account)
{}
//同步方法,用synchronized修饰某个方法
public synchronized void draw()
{}

(2)Lock

使用Lock可以显示定义同步锁对象来实现同步。其有一个实现类ReentrantLock(可重复锁)。

class x
{ 
   //定义锁对象
   private final ReentrantLock Lock=new ReentrantLock();
   //……
   //定义需要保证线程安全的方法
   public void m()
   { 
      lock.lock();
      try{
         //需要保证线程安全的代码
         //……
      }
      //使用finally来释放锁
      finally{
         lock.unlock();
      }
   }
}
  • 11
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

卡夫卡的熊kfk

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值