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

Java多线程

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

Java多线程

一.程序

程序是一段静态的代码,它是应用软件执行的蓝本

二.进程

进程是程序的一次动态执行过程,它对应从代码加载、执行至执行完毕的一个完整过程,这个过程也是进程本身从产生、发展至消亡的过程。如果把银行一天的工作比作一个进程,那么早上打上班铃是进程的开始,晚上打下班铃是进程的结束。

三.线程

线程是比进程更小的执行单位。一个进程在其执行过程中,可以产生多个线程,形成多条执行线索,每条线索,即每个线程也有它自身产生、存在和消亡的过程,也是一个动态的概念。就像银行一天的工作开始后,可以有多个不同的“线程”为客户服务,如财会部门,出纳部门,保安部门等。我们知道,每个进程都有一段专用的内存区域,与此不同的是,线程间可以共享相同的内存单元(包括代码与数据),并利用这些共享单元来实现数据交换、实时通信与必要的同步操作。比如在银行一天的工作开始后,财会部门、出纳部门、保安部门这三个线程共享银行的电力资源,财会部门、出纳部门可能共享银行的账目数据等。多线程的程序能更好地表达和解决现实世界的具体问题,是计算机应用开发和程序设计的一个必然发展趋势。

当然重点还是线程

下面进行代码解释:

单线程



//这是一个类
public class  Demo01MainThread {
    public static void main(String[] args) {
        Person p1=new Person("小强");
        p1.run();
        //System.out.println(0/0);//这行代码会报错,因为分母不能为0,所以程序就会从次中断,后面的代码将无法执行(单线程的缺点)
        Person p2=new Person("旺财");
        p2.run();
    }
}


//这是一个类
public class Person {
    private String name;

    public void run(){
        //定义循环,执行20次
        for (int i=0;i<20;i++){
            System.out.println(name+"-->"+i);

        }
    }

    public Person(String name) {
        this.name = name;
    }

    public Person() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

创建多线程的第一种方式


//这是一个类
public class Demo01Thread {
    public static void main(String[] args) {
        //3.创建Thread类的子类对象
        MyThread mt=new MyThread();
        //4.调用Thread类中的方法,start方法,开启新的线程,执行run方法
        mt.start();

        for (int i=0;i<20;i++){
            System.out.println("main:"+i);
        }
    }
}

//这是一个类
//1.创建一个Thread类的子类
public class MyThread extends Thread{
    //2.在Thread类的子类中重写Thread类中的run方法,设置线程任务(开启线程要做什么?)
    @Override
    public void run() {
        for (int i=0;i<20;i++){
            System.out.println("run:"+i);
        }
    }
}

多线程原理_随机打印的结果(接着上面的代码)

 多线程原理_多线程内存图解

Thread类的常用方法_获取线程名称



//定义一个Thread类的子类
public class MyThread extends Thread {
    //重写Thread类中的run方法,设置线程任务
    @Override
    public void run() {
        //获取线程的名称
        //String name = getName();
        //System.out.println(name);


        //Thread t = Thread.currentThread();
        //System.out.println(t);
        //String name = t.getName();
        //System.out.println(name);

        //链式编程
        System.out.println(Thread.currentThread().getName());

    }
}

//


public class Demo01GetThreadName {
    public static void main(String[] args) {
        //创建Thread类的子类对象
        MyThread mt=new MyThread();
        //调用start方法,开启新线程,执行run方法
        mt.start();

        new MyThread().start();
        new MyThread().start();

        //链式编程
        System.out.println(Thread.currentThread().getName());
    }
}

 Thread类的常用方法_设置线程的名称


//
public class MyThread02 extends Thread{

    public MyThread02(){

    }
    public MyThread02(String name){
        super(name);//把线程名称传递给父类。让父类(Thread)给子线程起一个名字
    }
    @Override
    public void run() {
        //获取线程的名称
        System.out.println(Thread.currentThread().getName());
    }
}


//
public class Demo01SetThreadName {
    public static void main(String[] args) {
        //开启多线程
        MyThread02 mt=new MyThread02();
        mt.setName("小强");
        mt.start();


        //开启多线程
        new MyThread02("旺财").start();
    }
}

创建多线程的第二种方法



//
public class Demo01Runnable {
    public static void main(String[] args) {
        //3.创建一个Runnable接口的实现类对象
        RunableImpl run=new RunableImpl();
        //4.创建一个Thread类对象,构造方法中传递Runnable接口的实现类对象
        Thread t=new Thread(run);
        //5.调用Thread类中的start方法,开启新的线程执行run方法
        t.start();

        for (int i=0;i<20;i++){
            System.out.println(Thread.currentThread().getName()+"-->"+i);
        }
    }
}


//
//1.创建一个Runnable接口的实现类
public class RunableImpl implements Runnable{
    //2.在实现类中重写Runnable接口的run方法,设置线程任务
    @Override
    public void run() {
        for (int i=0;i<20;i++){
            System.out.println(Thread.currentThread().getName()+"-->"+i);
        }
    }
}

匿名内部类来创建线程


public class DemoInnerClassThread {
    public static void main(String[] args) {
        //线程的父类是Thread
        //new MyThread().start
        new Thread(){
            //重写run方法,设置线程任务

            @Override
            public void run() {
                for (int i=0;i<20;i++){
                    System.out.println(Thread.currentThread().getName()+"-->"+"孙佳驰");
                }
            }
        }.start();

        //线程的接口Runnable
        //Runnable r=new RunnableImpl();//多态
        Runnable r = new Runnable() {
            //重写run方法,设置线程任务
            @Override
            public void run() {
                for (int i = 0; i < 20; i++) {
                    System.out.println(Thread.currentThread().getName() + "-->" + "程序员");
                }
            }
        };
        new Thread(r).start();

        //简化接口方式
        new Thread(new Runnable() {
            //重写run方法,设置线程任务
            @Override
            public void run() {
                for (int i = 0; i < 20; i++) {
                    System.out.println(Thread.currentThread().getName() + "-->" + "程序员2");
                }
            }
        }).start();
    }
}

线程安全问题的概述

线程安全问题的代码实现(这里的代码是有线程安全问题的问题代码) 


//这是一个类
public class RunnableImpl implements Runnable {
    //定义一个叫多个线程共享的票源
    private int ticket=100;


    //设置线程任务:买票
    @Override
    public void run() {
        //使用死循环,让买票重复执行
        while (true){
            //先判断票是否存在
            if (ticket>0){
                //提高安全问题的概率,让程序睡眠一下
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                //票存在,买票 ticket--
                System.out.println(Thread.currentThread().getName()+"正在卖第"+ticket+"张票");
                ticket--;
            }
        }
    }
}

//这是一个类

public class Demo01Ticket {
    public static void main(String[] args) {
        //创建一个Runnable接口的实现类对象
        RunnableImpl run=new RunnableImpl();
        //创建Thread类对象,构造方法中传递Runnable接口的实现类对象
        Thread t0=new Thread(run);
        Thread t1=new Thread(run);
        Thread t2=new Thread(run);
        //调用start方法开启多线程
        t0.start();
        t1.start();
        t2.start();
    }
}

线程安全问题产生的原理

解决线程安全问题_同步代码块


//这是一个类
public class RunnableImpl implements Runnable {
    //定义一个叫多个线程共享的票源
    private int ticket=100;

    //创建一个锁对象
    Object obj=new Object();

    //设置线程任务:买票
    @Override
    public void run() {
        //使用死循环,让买票重复执行
        while (true){
            //同步代码块
            synchronized (obj){
                //先判断票是否存在
                if (ticket>0){
                    //提高安全问题的概率,让程序睡眠一下
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    //票存在,卖票 ticket--
                    System.out.println(Thread.currentThread().getName()+"正在卖第"+ticket+"张票");
                    ticket--;
                }
            }
        }
    }
}


//这是一个类

public class Demo01Ticket {
    public static void main(String[] args) {
        //创建一个Runnable接口的实现类对象
        RunnableImpl run=new RunnableImpl();
        //创建Thread类对象,构造方法中传递Runnable接口的实现类对象
        Thread t0=new Thread(run);
        Thread t1=new Thread(run);
        Thread t2=new Thread(run);
        //调用start方法开启多线程
        t0.start();
        t1.start();
        t2.start();
    }
}

 同步技术的原理

解决线程安全问题_同步方法


//
public class RunnableImpl implements Runnable {
    //定义一个叫多个线程共享的票源
    private int ticket=100;


    //设置线程任务:买票
    @Override
    public void run() {
        //使用死循环,让买票重复执行
        while (true){
            payTicket();
        }
    }
    
    public synchronized void payTicket(){
        //先判断票是否存在
        if (ticket>0){
            //提高安全问题的概率,让程序睡眠一下
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            //票存在,买票 ticket--
            System.out.println(Thread.currentThread().getName()+"正在卖第"+ticket+"张票");
            ticket--;
        }
    }
}


//

public class Demo01Ticket {
    public static void main(String[] args) {
        //创建一个Runnable接口的实现类对象
        RunnableImpl run=new RunnableImpl();
        //创建Thread类对象,构造方法中传递Runnable接口的实现类对象
        Thread t0=new Thread(run);
        Thread t1=new Thread(run);
        Thread t2=new Thread(run);
        //调用start方法开启多线程
        t0.start();
        t1.start();
        t2.start();
    }
}

 解决线程安全问题_Lock锁


//
public class RunnableImpl implements Runnable {
    //定义一个叫多个线程共享的票源
    private int ticket=100;

    //1.在成员位置创建一个ReentrantLock对象
    Lock l=new ReentrantLock();

    //设置线程任务:买票
    @Override
    public void run() {
        //使用死循环,让买票重复执行
        while (true){
            //2.在可能会出现安全问题的代码前调用Lock接口中的方法lock获取锁
            l.lock();

            //先判断票是否存在
            if (ticket>0){
                //提高安全问题的概率,让程序睡眠一下
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                //票存在,买票 ticket--
                System.out.println(Thread.currentThread().getName()+"正在卖第"+ticket+"张票");
                ticket--;
            }
            // 3.在可能会出现安全问题的代码后调用Lock接口中的方法unlock释放取锁
            l.unlock();
        }
    }
}


//
public class Demo01Ticket {
    public static void main(String[] args) {
        //创建一个Runnable接口的实现类对象
        RunnableImpl run=new RunnableImpl();
        //创建Thread类对象,构造方法中传递Runnable接口的实现类对象
        Thread t0=new Thread(run);
        Thread t1=new Thread(run);
        Thread t2=new Thread(run);
        //调用start方法开启多线程
        t0.start();
        t1.start();
        t2.start();
    }
}

 线程状态

 等待唤醒案例

等待唤醒案例代码实现

public class Demo01WaitAndNotify {
    public static void main(String[] args) {
        //创建锁对象,保证唯一
        Object obj=new Object();
        //创建一个顾客线程(消费者)
        new Thread(){
            @Override
            public void run() {
                //保证等待和唤醒的线程只能有一个在执行,需要使用同步技术
                synchronized (obj){
                    System.out.println("告诉老板要的包子的种类和数量");
                    //调用wait方法,放弃cup的执行,进入到WAITING状态(无限等待)
                    try {
                        obj.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    //唤醒之后执行的代码
                    System.out.println("包子已经做好了,开吃");
                }
            }
        }.start();

        //创建一个老板线程(生产者)
        new Thread(){
            @Override
            public void run() {
                //花5秒做包子
                try {
                    Thread.sleep(5000);//花五秒钟做包子
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                //保证等待和唤醒的线程只能有一个在执行,需要使用同步技术
                synchronized (obj){
                    System.out.println("老板5秒钟之后做好包子,告知顾客,可以吃包子了");
                    obj.notify();
                }
            }
        }.start();
    }
}

Object类中wait带参方法和notif


public class Demo02WaitAndNotify {
    public static void main(String[] args) {
        //创建锁对象,保证唯一
        Object obj=new Object();
        //创建一个顾客线程(消费者)
        new Thread(){
            @Override
            public void run() {
                //保证等待和唤醒的线程只能有一个在执行,需要使用同步技术
                synchronized (obj){
                    System.out.println("顾客1告诉老板要的包子的种类和数量");
                    //调用wait方法,放弃cup的执行,进入到WAITING状态(无限等待)
                    try {
                        obj.wait(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    //唤醒之后执行的代码
                    System.out.println("包子已经做好了,顾客1开吃");
                }
            }
        }.start();

        //创建一个顾客线程(消费者)
        new Thread(){
            @Override
            public void run() {
                //保证等待和唤醒的线程只能有一个在执行,需要使用同步技术
                synchronized (obj){
                    System.out.println("顾客2,告诉老板要的包子的种类和数量");
                    //调用wait方法,放弃cup的执行,进入到WAITING状态(无限等待)
                    try {
                        obj.wait(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    //唤醒之后执行的代码
                    System.out.println("包子已经做好了,顾客2开吃");
                }
            }
        }.start();
        //创建一个老板线程(生产者)
        new Thread(){
            @Override
            public void run() {
                //花5秒做包子
                try {
                    Thread.sleep(5000);//花五秒钟做包子
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                //保证等待和唤醒的线程只能有一个在执行,需要使用同步技术
                synchronized (obj){
                    System.out.println("老板5秒钟之后做好包子,告知顾客,可以吃包子了");
                    //obj.notify();//如果有多个等待线程,随机唤醒一个
                    obj.notifyAll();//唤醒所有等待的线程
                }
            }
        }.start();
    }
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/643189.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

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

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