欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java 之多线程

程序员文章站 2023-12-23 13:33:34
...

Java 多线程

进程:

  • 概述:也就是只正在运行的程序,cup资源分配的独立单位;只是为了获得资源;
  • 优点:提高cpu的使用率;这一点很多人不容理解:假如你现在是一个单核计算机,你开了好几个视频窗口在看视频(打开腾讯看NBA,同时打开了优酷在看电影而且同时有使用爱奇艺看电视剧,哈哈,夸张了哈),你同时将他们窗口缩小放在放在桌面上,想看哪个就看哪个,此时你可能会感觉他们是同一时间在共同运行着,这其实就是多进程的体现;那为什说多进程可以提高cpu的使用率呢?你既然可以同时打开多个软件去运行,而且这种感受让你感觉他们是共同运行着,你却只打开一个软件,是不是浪费了,是不是可以理解了呢!

线程:

  • 概述:进程中的单个顺序控制流,是一条执行路径,多线程也就是说一个进程中有多个执行路径;
  • 多线程的优点:提高cpu利用率;对于这一点的理解,也可以参考多进程的思维方式,比如说你用爱奇艺看视频的时候,爱奇艺软件上可能还有时间日期显示等,这是即浏览这视频线程,又可以去看时间几点了。
tips:
  1. 线程与线程共享“堆内存和方法区内存”,栈内存是独立的,一个线程一个栈;

  2. 有个多线程之后,main方法结束只是主线程栈中没有方法栈帧了,但是其他线程或者其他栈中还有栈帧,也就是说main方法结束后,程序可能还在运行。

多线程的生命周期:*

  • 一般会经历五个阶段:新建,就绪,运行,阻塞,死亡;

线程调度:

  1. 分时调度:
  2. 抢占式调度:java采用抢占式调度

线程控制语句**:

  1. public static void sleep(long millis) :线程休眠,注意它是静态的方法,该方法出现在哪个线程中,哪个线程将进入阻塞状态,也就是线程停止执行了,待休眠的时间过后又将回到就绪阶段,争夺cup时间片。阻塞但不释放锁。

  2. public void interrupt();线程中断(指的是当线程中有sleep,wait导致线程执行过程中受阻,interrupt可以去清除这种状态,然后继续往下执行。

  3. public final void join(): 加入线程,其他线程需要等它执行完毕后才能执行。加入线程的语句位置为:

//如果要让t1必须t2执行完后在执行,那么它的代码顺序:
//t2必须放在开始,而且jion必须跟在后面
t2.start();
t2.join();
t1.start();
  1. public static void** yield()**;礼让线程,让多个线程执行更加和谐,但不能保证每个线程一人一次。

  2. public final void** setDaemon**(boolean on)守候线程,当只剩下守候线程的时候,虚拟机停止,该方法必须在启动线程前调用(垃圾回收器就是一个守候线程)

同步代码块、同步方法及静态方法的锁***

  • 在上篇文章中说过线程的不安全问题,本章节在这块说明下如何去解决多线程的不安全问题:
    线程不安全问题的本质是由于线程执行的随机性,导致我们无法预期它的执行结果,所以当我们可以控制它们的执行过程,是不是就可以解决线程的不安全问题了!具体怎么操作呢?
    当一个代码块或者方法被synchronized修饰的时候,线程在执行的这里的时候,需要等待里面已有线程执行完毕后才能去执行,被synchronized修饰后会伴随有一个锁, 同步代码块、同步方法的锁称为对象锁,对象锁有多个,静态方法的锁称为类锁类锁只有一个
同步代码块及其锁:
  • 被synchronized括起来的代码就成为同步代码块,synchronized就类似给代码块安了个门,里面的this可以看做是一把锁,这个锁是一个具体的对象,可以是任意类的对象,也就是说你可以自己创建个类后创建个对象使用于此。
//注意,这里使用的多线程方式是实现Runnable接口
public class Test implements Runnable {    
    int i=100;    
    public void run() {    
     while (i>0){  
            synchronized (this){       
//当有多个线程执行(t1,t2,t3),当t1进入到 synchronized  中后,门就被锁上了,其它两
//个线程执行到这里的时候需要在次等待,等t1执行完成后释放了锁,然后才能再去争抢执行权
             if(i>0){
             System.out.println(Thread.currentThread.getName()+"------"+i--);   
             }    
        }      
    }   
    }
}


同步方法及其锁:
  • 同步方法:当一个类中的成员方法被**synchronized**修饰的时候,它就是同步方法;
    同步方法的锁是当前所创建的对象。如下代码class MyClass中的两个方法m1()和m2()都是同步方法,当这两个方法被run()调用的时候,它的锁对象就是MyClass m=new MyClass();当被多个线程执行的时候,这两个方法又是怎么执行的呢?
    详细的过程描述见代码中:
public class Test{
    public static void main(String[] args) throws InterruptedException {
    S s = new S();
    Thread s1=new Thread(s);
    Thread s2=new Thread(s);
    s1.setName("m1");
    s2.setName("m2");
    s2.start();
    s1.start();
    // Thread.sleep(1000);
    }
}

class S implements Runnable{
        MyClass m=new MyClass();
        //MyClass s=new MyClass();
    public void run() {
         if(Thread.currentThread().getName().equals("m1")){
              m.m1();
              
//MyClass中的成员方法m1()和m2()都被synchronized所修饰,所以在运行这段程序的
//时候,如果m1线程先抢到执行权的话,那么m2线程必须m1线程执行完成后才能执行,
//他们的锁对象就是当前创建的类的对象(MyClass m=new MyClass())
//线程与线程之间需不需要等待,只需要判断他们是不是同一把锁。

    }else {
        s.m2();
           }
     }
}

class MyClass{
    public synchronized void m1(){
        try {
                Thread.sleep(5000);
        } catch (InterruptedException e) {
              e.printStackTrace();
         }
          System.out.println("m1........");
    }
    public synchronized void m2(){
    
    //如果将m2****()方法上的synchronized去除,那么m2线程将不用在等待m1了
    
    System.out.println("m2.............");
    }
}
静态同步方法及其锁
  • 静态同步方法:顾名思义,同时被静态及同步所修饰的方法;
  • 静态同步方法的锁可以称之为类锁,类锁只有一个,这个怎么理解呢?看下面代码:
public class Test01 {
    public static void main(String[] args) {
        S s1=new S();
        S s2=new S();
        Thread m1=new Thread(s1);
        Thread m2=new Thread(s2);
        m1.setName("m1");
        m2.setName("m2");

     m1.start();
     m2.start();
    }
}
class S implements Runnable{

@Override
    public void run() {
        if(Thread.currentThread().getName().equals("m1")){
        MyClass.m1();
    }else {
    MyClass.m2();
    
    //由于m1和m2是静态同步方法,所以他们使用的锁是类锁,又因为类锁这有一个,所以无
    //论m1或m2谁先抢到cpu时间片,另一个都必须等其执行完成后在执行
    
        }
    }
}
class MyClass{
       public synchronized static void m1(){
    try {
         Thread.sleep(5000);
    } catch (InterruptedException e) {
        e.printStackTrace();
}
    System.out.println("m1..........");
}
    public synchronized static void m2(){
    System.out.println("m2.........");
    }
}


相关标签: Java之多线程

上一篇:

下一篇: