多线程_Java线程知识

本文深入探讨Java中的线程和进程,包括它们的定义和区别。通过示例详细解释如何使用Thread类和Runnable接口创建线程,以及线程同步的实现方式如synchronized关键字和Lock锁。此外,还讨论了线程安全和线程状态,阐述了线程死锁的概念。
摘要由CSDN通过智能技术生成

进程和线程

1、进程:进程是指一个内存中运行的应用程序,每个进程都有独立的一块内存空间,即称为进程空间或者虚空间
2、线程:指进程中的一次执行流程,一个进程可以运行多个线程,线程没有自己的虚拟地址空间,与进程内其他线程共享分配资源;线程包含的内容:指令指针、栈、寄存器集合、私有数据区

线程创建方式

1、Thread类:可以对Thread类进行派生并覆盖run方法

(1)构造方法:

方法名说明
public Thread()分配一个新的线程对象
public Thread(String name)分配一个指定名字的新的线程对象
public Thread(Runnable target)分配一个带有指定目标新的线程对象
public Thread(Runable target,String name)分配一个带有指定目标新的线程对象并指定名字

(2)常用方法:

方法名说明
public String getName()获取当前线程名称
public void start()导致此线程开始执行,Java虚拟机调用此线程的run方法
public void run此线程要执行的任务在此处定义代码
pulic static void sleep(long mills)使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行)
public static Thread currentThread()返回当前正在执行的线程对象引用

3、实例代码:

public class MyThread extends Thread{ 
/** 利用继承中的特点 * 将线程名称传递 进行设置 */ 
       public MyThread(String name){ 
           super(name); 
       }
       /** 重写run方法 * 定义线程要执行的代码 */ 
        public void run(){ 
           for (int i = 0; i < 20; i++) { //getName()方法 来自父亲
                 System.out.println(getName()+i);  
        }
     }
  }
public class Demo { 
    public static void main(String[] args) {
        System.out.println("这里是main线程"); 
        MyThread mt = new MyThread("小强"); mt.start();

         //开启了一个新的线程
        for (int i = 0; i < 20; i++) { 
             System.out.println("旺财:"+i);  
                 } 
             } 
        }
2、Runnable接口

1、重写run方法即可创建线程

2、实例代码:

public class MyRunnable implements Runnable{
   //Overridez注解方法重载了父类
   @Override
   public void run(){
      for(int i=0;i<20;i++){
          System.out.println(Thread.currentThread().getName()+" "+i);
     }
   }
}
public class Demo{
   public static void main(String[] args){
      //创建自定义类线程任务对象
      MyRunnable m=new MyRunnable();
      //创建线程对象
      Thread=new Thread(m,"狗");
      t.start();
      for(int i=0;i<20;i++){
      System.out.println("猫"+ i);
      }
     }
   }
Thread和Runnable的区别

1、Thread不适合资源共享,Runnable接口可以实现资源共享
2、Runnable适合多个相同的程序代码的线程去共享一个资源、可以避免Java中单继承的局限性,增加程序的健壮性,实现解耦操作,代码可以被多个线程共享;线程池只能放入实现Runnable类线程

3、匿名内部类方式实现线程的创建

1、使用匿名内部类的方式实现Runable接口,重写Runnable接口中的run方法
2、实例代码:

public class Nameinner{
  public static void main (String[] args){
     Runnable r=new new Runnable(){
       public void run(){
          for(int i=0;i<20;i++){
            System.out.println("张三"+i);
       }
     } ;
     new Thread(r).start();
     for(int i=0;i<20:i++){
        System.out.println("李四"+i);
        }
  }
}

线程安全

1、定义:多个线程同时运行,而同时运行同个代码,程序每次运行结果和单线程运行的结果是一样的,而且其他变量和预期值是一样的,称为线程安全。线程安全问题都是由全局变量及静态变量引起的,若每个线程中对全局变量、静态变量只有读操作而无写操作,一般这个全局变量是线程安全的,如有多个线程同时执行写操作,需要考虑线程同步,否则可能影响线程安全。

线程同步

1、当多线程访问同一个资源的且有写操作的时候,容易出现线程安全问题。为了解决该问题Java提供了同步机制(synchronized)
2、完成同步的三种方式:
(1)同步代码块
(2)同步方法
(3)锁机制

同步代码块

1、synchronized关键字可以用于方法中的区块中,来表示只对这块的资源实现互斥访问。
2、格式:

synchronized(同步锁){
      需要同步的代码块
}

3、同步锁:对象的同步锁为一种概念,可以想象在对象上标记了一个锁,锁对象可以是任意类型,多个线程对象要使用同一把锁

4、实例代码:

public class Ticket implements Runnable{
   private int ticket = 100;
    Object lock = new Object(); 
    
    /** 执行卖票操作 */ 
    @Override 
    public void run() {
     
    //每个窗口卖票的操作 
    //窗口 永远开启 
    while(true){ synchronized (lock) { 
       if(ticket>0){
       
      //有票 可以卖 //出票操作 //使用sleep模拟一下出票时间 
      try {Thread.sleep(50); } catch (InterruptedException e) {
       
      // TODO Auto‐generated 
      catch block e.printStackTrace(); 
      }
      
      //获取当前线程对象的名字
       String name = Thread.currentThread().getName(); 
       System.out.println(name+"正在卖:"+ticket--);
                 }
             }  
          }
      }
}
同步方法

1、同步方法使用synchronized修饰的方法,就是同步方法,保证A线程在执行时,其它线程只能处于等待

2、格式:

public synchronized void method(){
  可能会产生线程安全问题的代码
}

3、实例代码:

public class Ticket implements Runnable{ 
     private int ticket = 100; 
     
     /** 执行卖票操作 */ 
     @Override 
     public void run() {
     
      //每个窗口卖票的操作 //窗口 永远开启 
      while(true){ sellTicket(); 
        } 
     }
     
     /** 锁对象 是 谁调用这个方法 就是谁 * 隐含 锁对象 就是 this **/ 
     public synchronized void sellTicket(){ if(ticket>0){
     
     //有票 可以卖 //出票操作 //使用sleep模拟一下出票时间
      try {Thread.sleep(100); 
      } catch (InterruptedException e) { 
      
      // TODO Auto‐generated catch block 
      e.printStackTrace();
      
      //获取当前线程对象的名字
       String name = Thread.currentThread().getName(); 
       System.out.println(name+"正在卖:"+ticket‐‐); 
            } 
       } 
  }
Lock锁

1、Lock锁又称为同步锁
2、方法:
(1)public void lock(); //加同步锁
(2)public void unlock(); //释放同步锁
3、实例代码:

public class Ticket implements Runnable{ 
    private int ticket = 100;
     Lock lock = new ReentrantLock();

 /** 执行卖票操作 */
  @Override 
  public void run() { 
  
  //每个窗口卖票的操作 //窗口 永远开启 
     while(true){
        lock.lock(); if(ticket>0){

   //有票 可以卖 //出票操作 //使用sleep模拟一下出票时间
    try {
    Thread.sleep(50);
     } catch (InterruptedException e) { 

    // TODO Auto‐generated catch block 
    e.printStackTrace(); }

   //获取当前线程对象的名字 
   String name = Thread.currentThread().getName(); 
   System.out.println(name+"正在卖:"+ticket‐‐); }lock.unlock();
              }
       } 
 }

线程状态

1、线程状态转换图
在这里插入图片描述
2、线程状态
(1)线程状态分为五种,分别是,新建、就绪态、运行态、阻塞态、死亡态,而阻塞态分三种:等待阻塞、同步阻塞、其它阻塞

3、线程死锁
(1)两个线程都被阻塞,每个线程在等待另一个线程时会发生死锁

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

创制造机

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

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

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

打赏作者

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

抵扣说明:

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

余额充值