java-多线程

多线程

Process与Thread

注意:

很多多线程是模拟出来的,真正的多线程是指多个CPU即多核,如多个服务器,如果是模拟出来的就是在一个CPU的情况下在同一个 时间切换不同的工作,切换时间很短所以照成同时执行的错觉

  • 进程与程序相关联,程序师指令和数据的有序集合,其本身没有任何运行的含义,是一个静态的概念
  • 进程是执行程序的一次执行过程,是一个动态的概念,是系统资源分配的单位
  • 一个进程可以包含若干个线程,一个进程必须有一个线程不然这个进程没有意义,线程就是CPU调度和执行的单位

继承Thread

  1. 写一个类继承Thread
  2. 重写run方法
  3. 调用start()方法启动线程
  4. 线程交替执行
  5. 线程不一定立即执行,由CPU调度执行
  6. 不建议使用,避免OOP单继承局限性
public class Test extends Thread {

    public static void main(String[] args) {
        Test test = new Test();
        test.start();
        for (int i = 0; i <= 10; i++) {
            System.out.printf("执行主线程" + i + "\n");
        }

    }

    @Override
    public void run() {
        for (int i = 0; i <= 10; i++) {
            System.out.printf("执行子线程" + i + "\n");
        }
    }
}
执行主线程0
执行子线程0
执行主线程1
执行子线程1
执行主线程2
执行子线程2

实现Runable接口

  1. 实现Runable接口
  2. 重写run方法
  3. New一个Thread丢入Runable的实现类,start()启动
  4. 推荐使用,避免单继承局限性,灵活方便,方便同一个对象被多个线城使用
public class Test implements Runnable {

    public static void main(String[] args) {
        Test test = new Test();
        new Thread(test).start();
    }
    @Override
    public void run() {
        for (int i = 0; i < 6; i++) {
            System.out.printf("测试" + i + "\n");
        }
    }
}
测试0
测试1
测试2
测试3
测试4
测试5

静态代理

  1. 找一个中间商实现附属功能,自己只需要做当前的事情即可
  2. 例子:A结婚,委托婚庆公司B,A只需要去结婚即可,B帮助其布置场地以及收尾等等
//封装一个接口,即要做的事情
public interface Marry {
    //去结婚
    void toMarry();
}
/*
    代理角色,中间商
    实现Marry接口,即实现要做的事情
    在重写方法中实现附属工作,即布置场地收尾等等
    然后调用Body()方法,Body()就是要去结婚的人
 */
public class Server implements Marry {

    public static void main(String[] args) {
        new Server(new Body()).toMarry();
    }

    private Body body;

    public Server(Body body) {
        this.body = body;
    }

    @Override
    public void toMarry() {
        System.out.printf("布置现场" + "\n");
        body.toMarry();
        System.out.printf("收钱回家" + "\n");
    }
}
//结婚的人,只需要去结婚就行
public class Body implements Marry {
    @Override
    public void toMarry() {
        System.out.printf("男孩正在结婚" + "\n");
    }
}
输出结果:
布置现场
男孩正在结婚
收钱回家

线程五种状态

1. new Thread()代表新生
2. 调用start()进入就绪状态,等待CPU调度,不一定立即执行
3. CPU调度线程两种情况
   	1. 阻塞状态
        	1. 当调用sleep/wait/同步锁定时,线程进入阻塞状态,阻塞状态结束后继续进入就绪状态等段CPU调度
       	2. 死亡状态
         	1. 线程中断/结束,一旦进入该状态线程就不能再次启动

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KOJv173E-1614066334796)(C:\Users\Administrator\Desktop\aa.png)]

线程停止

  1. 不推荐使用JDK提供的stop()/destory()方法
  2. 推荐线程自己销毁停止
  3. 建议使用一个线程销毁变量来停止线程操作
/*
        假停止
        返回值为True代码中执行停止线程操作,否则相反
     */
static boolean isStop = false;//默认不停止
public static boolean isStopThread(int a) {
    if (a > 10) {
        isStop = true;
    } else {
        isStop = false;
    }
    return isStop;
}

线程休眠

  • sleep存在异常InterrruptedExcetion
  • sleep时间达到后线程进入就绪状态
  • sleep可以模拟网络延时,倒计时等
  • 每一个对象都有一个锁,sleep不会释放锁
// sleep模拟倒计时
public static void main(String[] args) throws InterruptedException {
    toTest();
}

public static void toTest() throws InterruptedException {
    int number = 10;
    while (true) {
        Thread.sleep(1000);
        System.out.printf("" + number--);
        if (number <= 0) {
            break;
        }
    }
}

线程礼让

  • yield 让当前执行的线程停止,不阻塞
  • 将线程转为就绪状态
  • 礼让不一定成功,看CPU心情
public class TestYield {
    public static void main(String[] args) {
        YirldThread yirldThread = new YirldThread();
        new Thread(yirldThread, "a").start();
        new Thread(yirldThread, "b").start();
    }


    static class YirldThread implements Runnable {

        @Override
        public void run() {
            System.out.printf(Thread.currentThread().getName() + "线程开始" + "\n");
            Thread.yield();//礼让
            System.out.printf(Thread.currentThread().getName() + "线程停止" + "\n");
        }
    }
}

线程强制执行

  • Join合并线程,待此线程执行完成之后其他线程继续,其他线程阻塞
  • 通俗理解:插队
public class TestJoin implements Runnable {

    public static void main(String[] args) throws InterruptedException {
        TestJoin testJoin = new TestJoin();
        Thread thread = new Thread(testJoin);
        thread.start();
        for (int i = 0; i < 6; i++) {
            if (i == 3){//当Main线程运行到3的时候TestJoin线程插队,等待TestJoin运行完成Main线程继续
                thread.join();
            }
            System.out.printf("主线程" + i+"\n");
        }
    }

    @Override
    public void run() {
        for (int i = 0; i < 6; i++) {
            System.out.printf("子线程" + i+"\n");
        }
    }

}
主线程0
子线程0
主线程1
子线程1
主线程2
子线程2
子线程3
子线程4
子线程5
主线程3
主线程4
主线程5

线程优先级

  • 优先级用数字表示范围1-10
public class TestState {

    public static void main(String[] args) {
        A a = new A();
        Thread thread = new Thread(a);
        thread.setPriority(10);//设置优先级
        thread.start();
        System.out.printf("" + thread.getPriority());//获取优先级
    }


    static class A implements Runnable {

        @Override
        public void run() {

        }
    }
}

守护线程Daemon

  • 线程分为用户线程和守护线程
  • 虚拟机必须确保用户线程执行完毕
  • 虚拟机不用等待守护线程执行完毕
  • 比如:后台记录操作日志,监控内存,垃圾回收等守护线程
  • 用户线程执行完毕对应守护线程也随之结束
public class TestDaemon {

    public static void main(String[] args) {
        You you = new You();
        Server server = new Server();
        Thread thread = new Thread(server);
        thread.setDaemon(true);//设置守护线程
        thread.start();
        new Thread(you).start();//用户线程

    }

    //用户线程
    static class You implements Runnable {

        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                System.out.printf("凡人" + i + "\n");
            }
        }
    }

    //守护线程
    static class Server implements Runnable {

        @Override
        public void run() {
            while (true) {
                System.out.printf("上帝" + "\n");
            }
        }
    }
}

线程同步(安全性)

  • 由于一个进程的多个线程共享一块存储空间,所有存在冲突问题,为啦保证访问时的数据的正确性,在访问时加入锁synchronized,当一个线程获取这个对象的排它锁时,独占资源,其他线程必须等待,执行完成释放即可
  • 比如买票多个人抢一张票
  • 存在隐患
    • 一个线程持有锁会导致其他同样使用该锁的线程挂起
    • 在多线程竞争下,加锁释放锁会导致性能问题
    • 如果高优先级等待低优先级释放锁会导致性能倒置问题
  • synchronized锁的时当前this
  • 锁的对象一定是变化的量,增删改
//买票  同步锁(锁一个方法)
public class UnSecurity {

    public static void main(String[] args) {
        BuyPaio buyPaio = new BuyPaio();
        new Thread(buyPaio, "张三").start();
        new Thread(buyPaio, "李四").start();
        new Thread(buyPaio, "王五").start();
    }

    static class BuyPaio implements Runnable {

        private int num = 11;//余票

        boolean flag = true;//手动停止线程

        @Override
        public void run() {
            while (flag) {
                try {
                    toBuy();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        //synchronized同步方法  安全锁线程同步,不加锁可能买到负数票
        public synchronized void toBuy() throws InterruptedException {
            if (num <= 0) {
                flag = false;
                System.out.printf("暂无余票" + "\n");
                return;
            } else {
                Thread.sleep(100);
                num--;
                System.out.printf(Thread.currentThread().getName() + "买到第" + num + "张票" + "\n");
            }
        }
    }

}
//锁一个代码块
synchronized(Object){
    
}

死锁

  • 某一个同步代码块拥有两个以上对象的锁就可以死锁

Lock

  • 显示定义同步锁
public class TestLock {

    public static void main(String[] args) {
        BuyPaio buyPaio = new BuyPaio();
        new Thread(buyPaio, "张三").start();
        new Thread(buyPaio, "李四").start();
        new Thread(buyPaio, "王五").start();
    }

    static class BuyPaio implements Runnable {

        //定义Lock锁
        ReentrantLock lock = new ReentrantLock();
        private int num = 11;//余票

        boolean flag = true;//手动停止线程

        @Override
        public void run() {
            while (flag) {
                try {
                    lock.lock();//加锁
                    toBuy();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    lock.unlock();//解锁
                }
            }
        }

        //synchronized同步方法  安全锁线程同步,不加锁可能买到负数票
        public void toBuy() throws InterruptedException {
            if (num <= 0) {
                flag = false;
                System.out.printf("暂无余票" + "\n");
                return;
            } else {
                Thread.sleep(100);
                num--;
                System.out.printf(Thread.currentThread().getName() + "买到第" + num + "张票" + "\n");
            }
        }
    }
}

线程池

public class Main {

    public static void main(String[] args) {
        //创建线程池
        ExecutorService service = Executors.newFixedThreadPool(10);
        service.execute(new Test());
        service.execute(new Test());
        service.execute(new Test());
        service.execute(new Test());
        //关闭
        service.shutdown();
    }
}

class Test implements Runnable {

    @Override
    public void run() {
        System.out.printf("线程执行" + "\n");
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值