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

Java------多线程学习

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

Java------多线程学习

Java线程学习总结

今天把Java多线程学习了一下,作如下总结

进程与线程

进程是程序关于某个数据集合的一次执行过程
线程是操作系统能够运算调度的最小单位,是进程中单一顺序的控制流
一个进程可以并发执行多个线程,进程是线程的容器

例如:电脑QQ,QQ是进程,发送消息,QQ空间就是线程

单线程

单线程,就是程序执行时,进程中的线程顺序是连续的

package ThreadExample;



public class Singal_ThreadExample {
    //单线程演示
    //单线程,程序执行时,进程中的线程顺序是连续的
    public static void main(String[] args) {
        MyThread m1 = new MyThread("MyThread1");
        MyThread m2 = new MyThread("MyTHread2");

        m1.run();
        m2.run();

        //单线程的限制
        //m2调用run()方法,要等m1调用完了之后才可以继续调用

        //多线程可以实现上述结果交叉输出  多线程即进程可以并发执行
        //实际上所有的多线程代码执行顺序都是不确定的,每次执行的结果都是随机的。
    }
}

//单线程
class MyThread {
    String str;

    public MyThread(String str) {
        this.str = str;
    }

    void run() {
        for (int i = 0; i < 3; i++) {
            System.out.println("输入参数是: " + str);
        }
    }
}


多线程

多线程可以使单个程序内部在同一时刻执行多个代码段,完成不同的任务。一个复杂的任务可以分解为多个子任务交予线程执行,实现异步执行环境
多线程可以实现上述结果交叉输出 多线程即进程可以并发执行
例如,浏览器就是一个多线程的例子,可以浏览网页时同时播放声音和动画

多线程的实现方法

常用的两个,一是创建线程子类,继承Thread类;二是在定义的类中实现Runnable接口

创建Thread类的子类

创建一个类,继承Thread类并且重写其中的run()方法

package ThreadExample;



public class MyThreadExample {
    //创建Thread类的子类来实现多线程
    static class Thread1 extends Thread {
        private String str = null;

        public Thread1(String str) {
            this.str = str;
        }

        //重写Thread中的run()方法
        public void run() {
            for (int i = 0; i < 3; i++) {
                System.out.println("你输入的是:" + str);
                try {
                    //sleep(long millis): 在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)
                    //Thread.sleep()方法调用目的是不让当前线程独自霸占该进程所获取的CPU资源,以留出一定时间给其他线程执行的机会。
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) {
        Thread1 t1 = new Thread1("Thread1");
        Thread1 t2 = new Thread1("===============");
        Thread1 t3 = new Thread1("Thread2");

        t1.start();
        t2.start();
        t3.start();

        
    }
}

实现Runnable接口

Java不支持多线程,如果要继承Thread后就无法继承其他类,但是可以实现Runnable接口并且重写run()方法实现多线程

package ThreadExample;



public class RunnableExample {
    //实现Runnable

    static class Mythread implements Runnable {
        private String str;

        public Mythread(String str) {
            this.str = str;
        }

        //重写run()方法
        @Override
        public void run() {
            for (int i = 0; i < 3; i++) {
                System.out.println("你输入的是:" + str);
                try {
                    //Thread.sleep()方法调用目的是不让当前线程独自霸占该进程所获取的CPU资源,以留出一定时间给其他线程执行的机会。
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    public static void main(String[] args) {
        Mythread t1 = new Mythread("MyThread1");
        Mythread t2 = new Mythread("MyThread2");
        Mythread t3 = new Mythread("============");

        //将目标对象传递给Thread实例
        Thread thread1 = new Thread(t1);
        Thread thread2 = new Thread(t2);
        Thread thread3 = new Thread(t3);

        thread1.start();
        thread2.start();
        thread3.start();
    }
}

实现多线程分别打印0~99的数字的功能

实现多线程分别打印0~99的数字的功能

package ThreadExample.Practice;



public class Practice1 {
    static class MyThread extends Thread {

        private int num;

        public MyThread(int num) {
            this.num = num;
        }

        //重写Thread中的run()方法
        public void run() {
            //for (int i = 0; i < 100; i++) {
            System.out.println("num: " + num);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // }
        }
    }

    public static void main(String[] args) {
      
        for (int i = 0; i < 100; i++) {
            MyThread t1 = new MyThread(i);
            t1.start();
        }
    }
}

Runnable接口和Thread类的区别

两种方法都要执行start()方法来为线程分配系统资源,调度线程并且执行线程run()方法
当一个线程已经继承另一个类时,就应该使用Runnable接口来实现多线程

多线程的同步

如果一个程序激活了多个线程,并且多个线程共享同一资源,可能会发生冲突。这个时候就要使用进程的同步机制来解决
线程同步指的是通过特定的同步机制来控制多线程间的执行顺序,即使多个线程按照预定的先后次序执行

synchronized关键字

synchronized 关键字可以修饰方法或者代码块,相当于给修饰的方法或者代码块上锁,有效防止资源冲突

package ThreadExample;



public class SameThread {
    //线程同步问题
    public static int count = 10;

    //synchronized 关键字可以修饰方法或者代码块,相当于给修饰的方法或者代码块上锁,有效防止资源冲突
    public static synchronized int buyTicket() {
        if (count <= 0) {
            return -1;   //无票
        }

        count--;
        System.out.println("剩余票数: " + count);
        return count;
    }

    public static void main(String[] args) {
        for (int i = 0; i < 15; i++) {
            new Thread() {
                public void run() {
                    SameThread.buyTicket();
                }
            }.start();
        }
    }
}




同步锁的例题 三个窗口同时售卖20张票

多线程同步锁的应用 三个窗口同时售卖20张票

package ThreadExample.PracticeExample;



public class Example1 {
    //多线程同步锁的应用  三个窗口同时售卖20张票
    static class Sation extends Thread {

        public Sation(String name) {
            super(name);
        }

        static int count = 20;  //票数

        static Object object = "aa";   //创建一个同步锁 静态的钥匙

        //重写run方法
        public void run() {
            while (count > 0) {
                //使用一个锁, // 进去的人会把钥匙拿在手上,出来后才把钥匙拿让出来
                synchronized (object) {
                    if (count > 0) {
                        System.out.println(getName() + "卖出了第 " + count + "张票!");
                        count--;
                    } else {
                        System.out.println("票卖完了!");
                    }
                }
                try {
                    sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }


    }

    public static void main(String[] args) {
        Sation s1 = new Sation("站台1");
        Sation s2 = new Sation("站台2");
        Sation s3 = new Sation("站台3");

        s1.start();
        s2.start();
        s3.start();
    }
}




银行取钱1

两个人AB通过一个账户A在柜台取钱和B在ATM机取钱!

package ThreadExample.PracticeExample;


import java.util.Objects;

public class Example2 {
    //两个人AB通过一个账户A在柜台取钱和B在ATM机取钱!
    public static void main(String[] args) {
        Bank bank = new Bank();

        PersonA personA = new PersonA(bank, "ATM", "小明");
        PersonB personB = new PersonB(bank, "Counter", "小白");
        personA.start();
        personB.start();
    }

}

//银行类
class Bank {
    //账户的金额为1000
    static double money = 1000;

    //在柜台取钱
    public void Counter(double money) {
        this.money -= money;
        System.out.println("柜台取钱 " + money + "还剩 " + this.money);
    }

    //在ATM机取钱
    public void ATM(double money) {
        this.money -= money;
        System.out.println("ATM取钱 " + money + "还剩 " + this.money);
    }

    //提供一个对外取款的途径
    public synchronized void OutMoney(double money, String mode) throws Exception {
        if (money > this.money) {
            //检验余额是否充足
            throw new Exception("取款金额" + money + ",余额只剩" + this.money + ",取款失败!");
        }
        if (Objects.equals(mode, "ATM")) {
            ATM(money);
        } else {
            Counter(money);
        }
    }
}

//创建一个人类,模拟取钱  继承自Thread类
class PersonA extends Thread {
    //哪个银行
    private Bank bank;
    //何种方式
    private String mode;
    //姓名
    private String name;

    public PersonA(Bank bank, String mode, String name) {
        this.bank = bank;
        this.mode = mode;
        this.name = name;
    }

    @Override
    public void run() {
        while (bank.money >= 100) {
            try {
                bank.OutMoney(100, mode);
            } catch (Exception e) {
                e.printStackTrace();
            }
            try {
                sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class PersonB extends Thread {
    //哪个银行
    private Bank bank;
    //何种方式
    private String mode;
    //姓名
    private String name;

    public PersonB(Bank bank, String mode, String name) {
        this.bank = bank;
        this.mode = mode;
        this.name = name;
    }

    @Override
    public void run() {
        while (bank.money >= 200) {
            try {
                bank.OutMoney(200, mode);
            } catch (Exception e) {
                e.printStackTrace();
            }
            try {
                sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}


银行取钱2

编写一个模拟银行存款的程序。假设有两个储户都去银行往同一账户存款,一次存100,每次存3次。要求储户每存一次前,账户余额增加100,并在控制台输出当前账户的余额。

package ThreadExample.Practice;



public class Practice2 {
    public static void main(String[] args) {
        //进程同步锁的使用
        Bank bank = new Bank();
        Person a = new Person(bank);
        Person b = new Person(bank);
        Person c = new Person(bank);

        Thread t1 = new Thread(a);
        Thread t2 = new Thread(b);
        Thread t3 = new Thread(c);
        t1.start();
        t2.start();
        t3.start();
    }
}

//银行类
class Bank {
    //账户的初始金额为1000
    static double money = 1000;

    //存钱的方法
    public void SaveMoney(double getMoney) {
        money += getMoney;
        System.out.println("柜台存钱 " + getMoney + ",总金额为 " + money);
    }
}

//创建一个存钱的人类,模拟存钱
class Person implements Runnable {
    Bank bank;
    static Object object = "aa";  //创建一个同步锁

    public Person(Bank bank) {
        this.bank = bank;
    }

    //重写run()方法
    @Override
    public void run() {
        //存到3000块停止存钱
        while (bank.money < 3000) {
            //同步锁  金额随存钱次数的增加而不同步改变
            synchronized (object) {
                try {
                    bank.SaveMoney(100);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

欢迎大家指正,over
作者:爱吃水果的cc

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

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

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