JAVA 多线程

本文详细介绍了Java中的多线程概念,包括进程与线程的区别,以及并行与并发的含义。讲解了Java创建线程的两种方式:继承Thread类和实现Runnable接口,并探讨了线程同步的方法,如同步代码块、同步方法和进程通信机制。此外,还提到了JDK 5.0新增的Callable接口和线程池的概念,强调了线程同步和管理的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.进程 线程 并行 并发

进程:正在执行的程序段

线程:共享进程的堆和方法区,程序计数器和虚拟机栈每个线程各有一个,一个进程有多个线程

一个java应用程序至少有3个进程:main()主线程 gc()垃圾回收线程 异常处理线程

并行:多个cpu同时执行多个任务

并发:一个CPU采用时间片"同时"执行多个任务

多线程的优点:

  1. 提高应用程序的响应 对图形化界面更有意义,可增强用户体验

  2. 提高CPU利用率

2.创建线程与使用

java.lang.Thread

创建1.继承Thread类,重写run函数

创建实例,然后实例 . start():启动线程 并调用run方法

只用run方法的话不会新建线程,还是在总main()线程

Thread.currentThread,getName()获取当前进程的名字

对一个线程来说,只能start一次,不然会报错 只能新new一个

new Thread(){

public void run(){

}}

匿名类,重写run方法

currentThread() : 静态方法,返回执行当前代码的线程

getName()获取线程名字

setName() 设置线程名字 在启动前使用

yield() : 释放当前线程的执行权 但有可能下次又抢到了执行

join() : 如h1.join() 直到h1进程执行完之后原线程才会结束阻塞状态

stop() : 结束一个线程 该方法已过时,不建议使用

sleep(): 进程进入阻塞状态 参数为阻塞的时间

isAlive():判断进程是否还存活

创建2:实现接口Runnable

如果以一个实现类来创建几个进程的话,几个进程共享数据,可以实现共享数据不用static

Thread也实现了Runnable接口,本质上创建一个线程就是实现接口类里面的run方法

线程同步

某个线程对共享变量还没操作结束另一个进程也要读取、修改共享变量,这时就会出现问题

如何解决:当一个线程操作共享数据时,其他线程不能参与

操作不止包含修改删除,还有调用也是

同步机制:

方法一:

同步代码块:

//处理Runnable实现的方式
synchronized(同步监视器){
  //需要同步的代码:操作共享数据的代码
}
//同步监视器:锁,任何一个类的对象都可以充当锁 多个线程共用一个锁

//处理Thread继承方式:
//多个进程要创建n个实例对象,所以在初始化锁时,要加上static 


//锁可以用this 指向当前对象 不能用于继承方式 
//可以用window.class  window是类名 
    
方法二:

同步方法

如果操作共享数据的代码完整地声明在一个方法中,把这个方法定义为同步的

//解决Runnable
public synchronized coid show(){//同步监视器是this
    //代码与同步代码块内的代码相同
}
//解决继承Thread
public static synchronized void show(){//锁是类 window.class
    //保证内部函数也是静态的 Thread.currentThread.getName
}

单例模式 懒汉式

//使用同步机制将单例模式中的懒汉式改写为线程安全的
class Bank{
    private Bank(){}
    private static Bank instance = null;
    public static Bank getInstance(){
        //多个线程都调用该函数时,有可能会出现安全问题
        //处理方法:1 public static synchronized Bank getInstance()
        // 2 synchronzied (Bank.class){
        //  里面是if else 内容
        //  }
        /*if(instance==null){
            synchronized (Bank.class){
                if(instance == null){
                    instance = new Bank();
                }
          }
        }
        return instance;*/
  
        if(instance==null){
            instance = new Bank();
        }
        return instance;
    }
}
方式三
lock锁 jdk5新增

class Window implements Runnable(){
    private int ticket = 100;
    //实例化
    //可设置参数为true: private ReentrantLock lock = new ReentrantLock(true);一个线程解锁后不会立即又一次将资源分配给该进程
    private ReentrantLock lock = new ReentrantLock();
    //如果是继承的方式 lock要加上static
    public void(){
        while(true){
            try{
                lock.lock();
            }finally{
                lock.unlock();
            }
        }
    }
}

lock与synchronized不同
synchronized :自动释放同步监视器;有代码块,也有方法锁;隐式锁
lock: 需要手动启动、结束同步;只有代码块锁;JVM花费较少时间调度线程;性能更好;显式锁
lock > 同步代码块 > 同步方法
    
进程通信

wait() 使进程阻塞,该线程一阻塞,会释放锁,而sleep不会
notify()一旦执行会唤醒wait的优先级最高的那个线程
notifyAll() 唤醒所有

  1. 必须放在同步代码块或同步方法中
  2. 这三个方法的调用者必须是同步代码块或同步方法中的同步监视器
  3. 这三个方法定义在object类中

sleep与wait:

相同:都会使线程阻塞

不同:

  1. Thread类声明sleep() Object声明wait

  2. sleep可以在任何场景下 wait在同步代码块或同步方法

  3. 都在同步代码块或同步方法中 sleep不用释放锁 wait需要

生产者、消费者问题

class clert{
    private int number=0;
    public void add(){
        number = number+1;
    }
    public void seq(){
        number = number - 1;
    }
}
class producer extends Thread{
    private clert clerk;
    public producer(clert clerk){
        this.clerk = clert;
    }
    //用同一个clerk初始化该类
    public void run(){
        while(true){
            synchronized(){
                if(a.)
            }
        }
    }
}
class Consumer extends Thread{
    private clert clerk;
    public Comsumer(clert clerk){
        this.clerk = clert;
    }
    public void run(){
        while(true){
            synchronized(){
                if(a.number>0)
                {
                    a.seq();  
                }
            }
        }
    }
}
jdk 5.0新增线程创建方式
  1. 实现Callerable接口:可抛出异常、有返回值、支持泛型返回

    1. 创建一个实现Callable的实现类
    2. 实现call函数,线程完成的任务放在call函数中
    3. 创建Callable实现类的对象
    4. 将此对象传递给FutureTask构造器中
    5. 将FutureTask对象传到Thread构造器中
    class  myThread implements Callable{
        public Object call() throws Exception{
            int sum=0;
            return sum;
        }
    }
    public class A{
        psvm{
            myThread a = new myThread();
            FutureTask b = new FutureTask(a);
            new Thread(b).start();
            //FutureTask是唯一实现Future接口的实现类,同时也实现了Runnable,可以获得取消、获取 实现Callable和Runnable类 执行结果
            Object sum = b.get();//要try catch
        }
    }
    
  2. 使用线程池: 提前创建多个线程,放入线程池,使用时直接获取,使用完放回池中

    提高响应速度

    降低资源消耗

    便于线程管理

    corePoolSize

    maximumPoolSize

    keepAliveTime

    public class B{
        psvm(){
            ExecutorService service = Executors.newFisedThreadPool(10);
            //有10个进程的进程池
            service.execute();//参数为Runnable实现类
            service.submit();//参数为Callable实现类  有返回值
            service.shutdown();//关闭线程池
            
        }
    }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值