栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

java多线程

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

java多线程

常见概念 进程

每个进程(相当于应用程序)都有独立的代码和数据空间(内存),进程间的切换会有较大开销,一个进程包含1~n个线程。

线程

同一类线程(相当于同一程序的多个窗口)共享代码和数据空间,每个线程都有独立的运行程序和程序计数器。

多进程

操作系统能同时运行多个任务(程序)。

多线程

同一程序中有多个顺序流在执行。

线程的生命周期

实现一个线程的三种方式 第一种方式 继承Thread类
1.让一个类继承Thread类
public class A extends Thread{
    //2.重写run()方法
    public void run(){
        for (int i = 0; i <=40 ; i++) {
            //获取当前运行的线程名
            String threadName=Thread.currentThread().getName();
            System.out.println(threadName+":"+i);
        }
    }
​
    public static void main(String[] args) {
        A a1=new A();
        A a2=new A();
        //调用start()方法
        a1.start();
        a2.start();
    }
}

1.为什么书写的是run()方法,调用的却是start方法?

答:只有调用了 start()方法,才会表现出多线程的特性,不同线程的 run() 方法里面的代码交替执行。如果直接调用run()方法是面向对象中的方法调用,只有一个线程main,不具备多线程的特性。

2.为什么调用的是start方法,执行的却是run方法?

答:start()方法是线程启动方法,使得线程处于就绪状态等待cpu,当获取到cpu资源后会调用run()方法,交替执行方法中的内容。

3.为什么a1的run方法未执行完毕,a2的run方法就执行了?

答:因为a1和a2是两个线程,会进行资源抢占,谁抢到cpu谁就获取cup资源信息,且每次执行结果都不同。

第二种方式 实现Runnable接口
//创建线程的第二种方法
//①.实现Runnable接口
public class DemoB implements Runnable {
    //②.重写run方法
    public void run() {
        for (int i = 0; i <20 ; i++) {
            System.out.println(Thread.currentThread().getName()+":"+i);
        }
    }
    public static void main(String[] args) {
        //这个时候并不是新建状态,并不是一个线程对象
        DemoB b1=new DemoB();
        DemoB b2=new DemoB();
        // 产生2个线程去包装这两个任务b1,b2
        // 新建状态
        Thread t1=new Thread(b1);
        Thread t2=new Thread(b2);
        t1.start();
        t2.start();
    }
 }
第三种方式 实现Callable接口
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
//实现一个Callable接口
public class C implements Callable {
    //重写call方法,有返回结果
    int sum=0;
    public Object call() throws Exception{
        for (int i = 0; i <= 20; i++) {
            System.out.println(Thread.currentThread().getName()+":"+i);
            sum+=i;
        }
        return "1-20之和为:"+sum;
    }
    public static void main(String[] args) throws Exception{
        C c1=new C();
        C c2=new C();
        FutureTask ft1=new FutureTask(c1);
        FutureTask ft2=new FutureTask(c2);
        Thread t1=new Thread(ft1);
        Thread t2=new Thread(ft2);
        t1.start();
        t2.start();
        Object result1=ft1.get();
        Object result2=ft2.get();
        System.out.println(result1);
        System.out.println(result2);
    }
}
sychronized关键字

同步锁,有两种使用范围

①方法中加锁,保证线程安全,一次只有一个线程进入

②代码块加锁:sychronized(obj){

//对一段代码块上锁,一次可以有多个线程进入

}

// synchronized关键字的使用场景 同步锁
public class DemoF {
    private int count = 10;
    // 对当前方法上锁的方式 保证线程安全  场景一
    public synchronized void MethodA() {
        if (count > 0) {
            for (int i = 0; i < 10; i++) {
                System.out.println(Thread.currentThread().getName() + "执行了递减操作,还剩" + (count--));
                return;
            }
        } else {
            System.out.println("count值必须大于0!");
        }
    }
    private Object obj = new Object();
    public void MethodB() {
        System.out.println(Thread.currentThread().getName() + "开始执行递减操作....");
        //同步代码块
        synchronized (obj) {
            if (count > 0) {
                for (int i = 0; i < 10; i++) {
                    System.out.println(Thread.currentThread().getName() + "执行了递减操作,还剩" + (count--));
                    return;
                }
            } else {
                System.out.println("count值必须大于0!");
            }
        }
    }
    public static void main(String[] args) {
        DemoF f = new DemoF();
        for (int i = 0; i < 4; i++) {
            DemoF1 f1 = new DemoF1(f);
            Thread t1 = new Thread(f1);
            t1.start();
        }
    }
}
    class DemoF1 implements Runnable {
        private DemoF f;
        public DemoF1(DemoF f) {
            this.f = f;
        }
​
        public void run() {
            for (int i = 0; i < 10; i++) {
                f.MethodB();
            }
        }
    }
死锁

两个或两个以上的进程中每一个都在等待其中另一个进程释放资源,导致无法向前推进,这种现象称为死锁。

ThreadLocal关键字

本地线程,一个线程内部的存储类,可以在指定线程内存储数据,而且存储的数据只能在当前线程使用。

sleep、wait、yield、join方法 sleep()

睡眠方法,在锁资源中使用,线程会进入阻塞状态,sleep睡眠结束后不会立即释放锁资源,其他线程仍然无法访问,线程由阻塞态--->就绪态,不会立即变为运行态,要等待获取cpu资源。

//通过sleep演示线程阻塞
public class DemoD {
    public static void main(String[] args) {
        DemoD1 d1=new DemoD1();
        d1.start();
    }
 static class DemoD1 extends Thread{
     public void run() {
         for (int i = 1; i <= 10; i++) {
             System.out.println(Thread.currentThread().getName()+":"+i);
             try {
                 Thread.sleep(1000);
                 // 让当前线程睡眠1s 单位是毫秒  线程从运行状态--->阻塞状态
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }
             // 1s之后 阻塞时间到了  阻塞状态--->就绪状态--->运行状态
         }
     }
 }
}
wait()

让当前线程等待,也会让线程进入阻塞状态,是object类的一个方法,会释放锁资源,其他线程可以访问,wait方法只能在同步方法或同步代码块中使用,只能在有锁资源中使用。

wait()方法什么时候结束?

1.可以设置等待时间

2.通过notify方法唤醒等待的线程

public class DemoB {
    public static void main(String[] args) {
        DemoB3 a3 = new DemoB3();
        DemoB2 a2 = new DemoB2(a3);
        DemoB1 a1 = new DemoB1(a3);
        Thread t1 = new Thread(a1);
        Thread t2 = new Thread(a2);
        //启动2个线程,让两个线程进入就绪态
        t1.start();
        t2.start();
    }
}
​
class DemoB1 implements Runnable {
    private DemoB3 a3;
    public DemoB1(DemoB3 a3) {
        this.a3 = a3;
    }
​
    public void run() {
        a3.a();
    }
}
​
class DemoB2 implements Runnable {
    private DemoB3 a3;
​
    public DemoB2(DemoB3 a3) {
        this.a3 = a3;
    }
​
    public void run() {
        a3.b();
    }
}
class DemoB3 {
    public synchronized void a() {
        System.out.println("我是a方法,正在被" + Thread.currentThread().getName() + "线程执行");
        try {
            wait(1000);//让当前线程等待
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("我的阻塞原因解除");
    }
    public synchronized void b() {
        System.out.println("我是a方法,正在被" + Thread.currentThread().getName() + "线程执行");
        try {
            wait();//让当前线程等待
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("我的阻塞原因解除");
    }
    public synchronized void c(){
        notifyAll();//唤醒所有线程
    }
}
yield()

让当前线程暂停一下,不释放锁资源,线程不会进入阻塞状态,暂停结束后线程继续运行,建议在锁资源中使用(实际上无法保证yield方法达到让步目的,因为让步的线程可能被线程调度再次选中)

public class DemoC {
    public static void main(String[] args) {
        DemoC3 c3 = new DemoC3();
        DemoC2 c2 = new DemoC2(c3);
        DemoC1 c1 = new DemoC1(c3);
        Thread t1 = new Thread(c1);
        Thread t2 = new Thread(c2);
        //启动2个线程,让两个线程进入就绪态
        t1.start();
        t2.start();
    }
}
​
class DemoC1 implements Runnable {
    private DemoC3 c3;
    public DemoC1(DemoC3 c3) {
        this.c3 =c3;
    }
​
    public void run() {
       c3.a();
    }
}
​
class DemoC2 implements Runnable {
    private DemoC3 c3;
​
    public DemoC2(DemoC3 c3) {
        this.c3 = c3;
    }
​
    public void run() {
        c3.a();
    }
}
class DemoC3 {
    public  void a() {
        System.out.println("我是a方法,正在被" + Thread.currentThread().getName() + "线程执行");
        Thread.yield();//让当前线程暂停一下
        System.out.println("我的阻塞原因解除,继续执行"+Thread.currentThread().getName());
    }
    public synchronized void b() {
        System.out.println("我是b方法,正在被" + Thread.currentThread().getName() + "线程执行");
        Thread.yield();
        System.out.println("我的阻塞原因解除,继续执行"+Thread.currentThread().getName());
    }
}
join()

让路方法,等待调用join方法的线程结束后程序才能继续运行。

//join方法 让路方法 等待调用join方法的线程结束后 程序才能继续运行
public class DemoD {
    private static final Object obj=new Object();
    private static int count=0;//计数器
    public static void main(String[] args) throws Exception{
        DemoD1 d1=new DemoD1();
        DemoD2 d2=new DemoD2();
        Thread t1=new Thread(d1);
        Thread t2=new Thread(d2);
        t1.start();
        t2.start();
        //调用join方法的线程结束后 程序才能继续运行
        t1.join();
        t2.join();
        System.out.println("结果是:"+count);
    }
    static class DemoD1 implements Runnable{
        public void run(){
            synchronized(obj){
                System.out.println(Thread.currentThread().getName()+"准备执行");
                for (int i = 0; i <10 ; i++) {
                    count++;
                }
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"结束执行");
            }
        }
    }
    static class DemoD2 implements Runnable{
        public void run(){
            synchronized (obj){
                System.out.println(Thread.currentThread().getName()+"准备执行");
                for (int i = 0; i <10 ; i++) {
                    count++;
                }
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"结束执行");
            }
        }
    }
}
线程池

如果线程数量多且每个线程执行时间短,可以通过线程池实现复用。

单线程池

池子中有且仅有一个线程,无论多少任务都由这一个线程处理

public class DemoF {
    public static void main(String[] args) {
        //产生了一个单线程的线程池
        ExecutorService service= Executors.newSingleThreadExecutor();
        //模拟了一百个任务
        for (int i = 0; i <100 ; i++) {
            DemoF1 f1=new DemoF1();
            service.execute(f1);
        }
    }
}
class DemoF1 implements Runnable{
    public void run(){
        System.out.println(Thread.currentThread().getName()+"执行了任务!");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
定长线程池(常用)

线程个数是固定的

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
​
public class DemoG {
    //产生了一个定长线程池 个数固定 四个
    public static void main(String[] args) {
        ExecutorService service= Executors.newFixedThreadPool(4);
        for (int i = 0; i <100 ; i++) {
            DemoG1 g1=new DemoG1();
            service.execute(g1);
        }
    }
}
class DemoG1 implements Runnable{
    public void run(){
        System.out.println(Thread.currentThread().getName()+"执行了任务!");
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
可缓存线程池
public class DemoH {
    public static void main(String[] args) {
        //创建可缓存线程池 如果线程池长度超过处理需要,可灵活回收空闲线程和创建新线程 若无可回收,则创建新线程
        ExecutorService service= Executors.newCachedThreadPool();
        for (int i = 0; i < 100; i++) {
            DemoH1 h1=new DemoH1();
            
            service.execute(h1);
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
class DemoH1 implements Runnable{
    public void run(){
        System.out.println(Thread.currentThread().getName()+"执行了任务!");
    }
}
定时器线程池
public class DemoI {
    public static void main(String[] args) {
        ScheduledExecutorService service= Executors.newScheduledThreadPool(4);
            DemoI1 i1=new DemoI1();
            //延迟5s后开始执行任务
           //service.schedule(i1,5, TimeUnit.SECONDS);
        //延迟5s后开始执行任务 并且每个1s后在执行一次
        service.scheduleAtFixedRate(i1,5,1,TimeUnit.SECONDS);
    }
}
class DemoI1 implements Runnable{
    public void run(){
        System.out.println(Thread.currentThread().getName()+"执行了任务!");
    }
}
shutdown和shutdownNow的区别

shutdown会等待线程池中的任务执行完成后关闭线程池,并且不会接受新任务shutdownNow会给所有正在运行的线程发送中断信号,试图(不一定能立即关闭)中断任务的执行,然后关闭线程池

public class DemoJ {
    public static void main(String[] args) {
      a();
    }
    public static void a(){
        ExecutorService service= Executors.newFixedThreadPool(2);
        for (int i = 0; i <20 ; i++) {
            DemoJ1 j=new DemoJ1();
            service.execute(j);
        }
        service.shutdown();
        try {
            boolean b=service.awaitTermination(5, TimeUnit.SECONDS);
            //判断当前线程池状态 true:正常终结 flase:没有关闭
            System.out.println(b);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("执行了shutdown()方法");
    }
    public static void b(){
        ExecutorService service= Executors.newFixedThreadPool(2);
        for (int i = 0; i <20 ; i++) {
            DemoJ1 j=new DemoJ1();
            service.execute(j);
        }
        service.shutdownNow();
        try {
            boolean b=service.awaitTermination(3, TimeUnit.SECONDS);
            System.out.println(b);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("执行了shutdownNow()方法");
    }
}
class DemoJ1 implements Runnable{
    public void run(){
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"执行了");
    }
}

excecute()和submit()都是像线程池中提交任务excute针对的是Runnable()的任务,sumbit针对的是Callable的任务(有返回结果)

定时器---TimerTask

public class DemoK {
    public static void main(String[] args) {
        DemoK1 k1=new DemoK1();//产生了一个定时任务对象
        Timer timer=new Timer();//负责执行定时任务的对象
       // timer.schedule(k1,5000);//5s后开始执行任务
        //timer.schedule(k1,5000,1000);//5s后开始执行任务,每隔1s执行一次
        //在具体时间执行该任务
        Date date=new Date(122,5,23,19,13,0);
        timer.schedule(k1,date);
    }
}
class DemoK1 extends TimerTask {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"执行了该方法!");
    }
}
CountDownLatch 工具类

同步工具类 让一个或多个线程等待 直到其他线程执行完后才执行 类似join()方法

public class DemoL {
    public static void main(String[] args) {
        CountDownLatch cdl=new CountDownLatch(4);
        for (int i = 0; i <4 ; i++) {
            DemoL1 l1=new DemoL1(cdl);
            Thread t1=new Thread(l1);
            t1.start();
        }
        System.out.println("内容必须等待所有线程结束才执行");
        try {
            cdl.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("你好,中国");
    }
}
class DemoL1 implements Runnable{
    private CountDownLatch cdl;
​
    public DemoL1(CountDownLatch cdl) {
        this.cdl = cdl;
    }
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"执行了!");
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"结束了!");
        //标注线程结束了
        cdl.countDown();
    }
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/946592.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号