• JavaSE-多线程


    package com.btp.t4.多线程;
    
    /*
     * 单线程:一条线可以串起来的
     */
    public class TestMain{
        public static void main(String[] args){
            method2("btp");
        }
    
        private static void method2(String str) {
            // TODO 自动生成的方法存根
            System.out.println("method2");
            method1(str);
        }
    
        private static void method1(String str) {
            // TODO 自动生成的方法存根
            System.out.println("method1");
            System.out.println(str);
        }
    }
    TestMain
    package com.btp.t4.多线程;
    /*
     * 创建一个子线程,完成1-100之间自然数的输出。同样地,主线程执行同样的操作
     * 创建多线程的第一种方式:继承Thread类
     */
    public class TestThread {
        public static void main(String[] args){
            //3.创建一个子类的对象
            SubThread st=new SubThread();
            //4.调用线程的start()方法:启动此线程;调用相应的run()方法
            st.start();//一个线程对象只能够执行一次start(),可以再创建一个对象
            //st.run();//只调用run().并没有启动此线程
            SubThread st1=new SubThread();
            st1.start();
            for(int i=1;i<=100;i++){
                System.out.println(Thread.currentThread().getName()+":"+i);
            }
        }
    }
    
    //1.创建一个继承Thread的子类
    class SubThread extends Thread{
        //2.重写Thread类的run()方法。方法内实现此子线程要完成的功能
        public void run(){
            for(int i=1;i<=100;i++){
                System.out.println(Thread.currentThread().getName()+":"+i);
            }
        }
    }
    TestThread
    package com.btp.t4.多线程;
    
    public class TestThread1 {
        public static void main(String[] args)
        {
            PrintNum1 p=new PrintNum1();
            Thread t1=new Thread(p);
            Thread t2=new Thread(p);
            t1.start();
            t2.start();
            
        }
    }
    
    class PrintNum1 implements Runnable{
    
        @Override
        public void run() {
            // TODO 自动生成的方法存根
            for(int i=1;i<=100;i++)
            {
                if(i%2==0)System.out.println(Thread.currentThread().getName()+":"+i);
            }
        }
        
    }
    TestThread1
    package com.btp.t4.多线程;
    
    public class TestTwoThread {
        public static void main(String[] args){
    //        Thread t1=new Thread1();
    //        t1.start();
    //        t1=new Thread2();
    //        t1.start();
            
            new Thread(){
                public void run(){
                    for(int i=1;i<=100;i++)
                    {
                        if(i%2==0)System.out.println(Thread.currentThread().getName()+":"+i);
                    }
                }
            }.start();
            new Thread(){
                public void run(){
                    for(int i=1;i<=100;i++)
                    {
                        if(i%2!=0)System.out.println(Thread.currentThread().getName()+":"+i);
                    }
                }
            }.start();
        }
    }
    
    class Thread1 extends Thread{
        public void run(){
            for(int i=1;i<=100;i++)
            {
                if(i%2==0)System.out.println(Thread.currentThread().getName()+":"+i);
            }
        }
    }
    
    class Thread2 extends Thread{
        public void run(){
            for(int i=1;i<=100;i++)
            {
                if(i%2!=0)System.out.println(Thread.currentThread().getName()+":"+i);
            }
        }
    }
    TestTwoThread
    package com.btp.t4.多线程;
    /*
     * 继承的方式:模拟火车站售票窗口,开启三个窗口售票,总票数为100张
     * 存在线程安全问题
     */
    
    public class TestWindow {
        public static void main(String[] kobe)
        {
            Window w1=new Window();
            Window w2=new Window();
            Window w3=new Window();
            
            w1.setName("窗口1");
            w2.setName("窗口2");
            w3.setName("窗口3");
            
            w1.start();
            w2.start();
            w3.start();
            
        }
    }
    
    class Window extends Thread{
        static int ticket=100;//如果不声明为static,就是300张
        //Object obj=new Object();也不能当锁,三个对象,三把锁
        static Object obj=new Object();//共用一把锁
        public void run(){
            while(true){
                synchronized(obj){//this代表当前对象,而有三个对象,所以创建了3个锁,所以不能使用this
                if(ticket>0){
                    try {
                        Thread.currentThread().sleep(100);
                    } catch (InterruptedException e) {
                        // TODO 自动生成的 catch 块
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"售票,票号为:"+ticket--);
                }else{
                    break;
                }
                }
            }
        }
    }
    TestWindow
    package com.btp.t4.多线程;
    /*
     * 实现的方式:模拟火车站售票窗口,开启三个窗口售票,总票数为100张
     */
    /*
     * 创建多线程的第二种方式:通过实现的方式
     * 1.创建一个实现了Runnable接口的类
     * 2.实现Runnable内的Run()方法
     * 3.创建一个实现类的对象
     * 4.将此对象作为形参传入Thread类的构造器中,创建Thread类的对象,此对象作为一个线程
     * 5.调用start()方法,执行run()
     * 
     * 
     * 对比继承的方式   VS 实现的方式
     * 1.联系:Thread类本身就实现了Runnable接口
     * 2.哪个方式好:实现的方式优于继承的方式
     *     ①实现的方式避免了java单继承的局限性
     *     ②如果多个线程要操作同一份资源(数据),更适合使用实现的方式
     *     
     *     
     *此程序存在线程安全问题,打印车票时,会出现重票,错票
     *1.存在的原因:由于一个线程在操作共享数据的过程中,未执行完毕的情况下,另外的线程参与进来,
     *  导致共享数据存在安全问题
     *2.如何解决线程的安全问题?
     *  必须让一个线程操作共享数据完毕以后,其他线程才有机会参与共享数据的操作
     *3.java如何实现线程的安全:线程的同步机制
     *       方式1:同步代码块
     *           synchronized(同步监视器){
     *           //需要被同步的代码块(即为操作共享数据的代码)
     *           }
     *           1.共享数据:多个线程共同操作的同一个数据(变量)
     *           2.同步监视器:由一个类的对象来充当。哪个线程获取此监视器,谁就执行大括号里被同步的代码。俗称:锁
     *           3.同步监视器可以是任何类的对象 ,要求所有线程共用一把锁
     *       方式2:同步方法
     *            将操作共享数据的方法声明为synchronized。即此方法为同步方法,能够保证当其中一个线程执行此方法时,
     *            其它线程在外等待直至此线程执行完此方法
     *            >同步方法的锁:this
     *4.线程同步的弊端:由于同一个时间只能有一个线程访问共享数据,效率变低了
     */
    public class TestWindow1 {
    
        public static void main(String[] args) {
            //要想启动一个多线程,必须调用start()
            //Runnable接口内并没有start()方法,只有Thread及其子类才有
            //把实现Runnable接口的类的对象传入Thread构造器,通过Thread对象来调用start()
            Window1 w=new Window1();//只有一个Window1对象,所以只有100张票
            new Thread(w).start();
            new Thread(w).start();
            new Thread(w).start();
    
        }
    
    }
    
    
    class Window1 implements Runnable{
        int ticket=100;//共享数据
        Object obj=new Object();//监视器:初始是“绿灯”,每次有线程操作共享数据,就变成“红灯”,表示不允许其他线程再去操作共享数据。
                                //只有一个线程操作完这个共享数据,才会转为“绿灯”,再允许其他线程操作
        public void run(){
            while(true){
                //Object obj=new Object();//也不能写在这里,写在这里就是每个线程一把锁
                synchronized(obj){//这里不能写new Object();因为每次new了之后,都生成一把锁,都是“绿灯”,都允许进入。不安全。
                if(ticket>0){
                    try {
                        Thread.currentThread().sleep(10);
                    } catch (InterruptedException e) {
                        // TODO 自动生成的 catch 块
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"售票,票号为:"+ticket--);
                }else{
                    break;
                }
                }
            }
        }
        
        //同步方法,然后run()调用此方法就可以了
        public synchronized void show()
        {
            
                if(ticket>0){
                    try {
                        Thread.currentThread().sleep(10);
                    } catch (InterruptedException e) {
                        // TODO 自动生成的 catch 块
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"售票,票号为:"+ticket--);
                }
            
        }
        
    }
    TestWindow1
    package com.btp.t4.多线程;
    /*
     * Thread的常用方法:
     * 1.start():启动线程并执行相应的run()方法
     * 2.run():子线程要执行的代码放入run()方法中
     * 3.Thread.currentThread():静态的,调取当前的线程
     * 4.getName():获取此线程的名字
     * 5.setName():设置此线程的名字
     * 6.yield():调用此方法的线程释放当前CPU的执行权
     * 7.join():在A线程中调用B线程的join()方法。表示:当执行到此方法,A线程停止执行,直至B线程执行完毕,
     * A线程再接着join()之后的代码执行
     * 8.isAlive():判断当前线程是否还存活
     * 9.sleep(long l):显式的让当前线程睡眠l毫秒
     * 10.线程通信:wait()  notify()  notifyAll()
     * 
     * 设置线程的优先级:
     * getPriority():返回线程优先级
     * setPriority(ine newPriority):设置线程的优先级:概率变大了,不是百分百
     * 
     */
    public class TestThreadMethod {
        public static void main(String[] args){
            SubThread1 st1=new SubThread1();
            st1.setPriority(Thread.MAX_PRIORITY);
            st1.start();
            System.out.println(st1.getName());
            st1.setName("子线程1");
            
            Thread.currentThread().setName("主线程");
            System.out.println(Thread.currentThread().getName()+"!!!!!!!!");
            
            
                for(int i=1;i<=100;i++){
                    //if(i%10==0)Thread.currentThread().yield();
                    System.out.println("--------"+Thread.currentThread().getName()+":"+i);
                    if(i==20)
                        try {
                            st1.join();
                        } catch (InterruptedException e) {
                            // TODO 自动生成的 catch 块
                            e.printStackTrace();
                        }
            }
            
            
            //SubThread1 st2=(SubThread1) Thread.currentThread();//调用的是主线程,报错
            //System.out.println(st2.getName());
            System.out.println(st1.isAlive());
        }
        
    }
    
    
    class SubThread1 extends Thread{
        //2.重写Thread类的run()方法。方法内实现此子线程要完成的功能
        public void run(){
            try {
                Thread.currentThread().sleep(100);
            } catch (InterruptedException e) {
                // TODO 自动生成的 catch 块
                e.printStackTrace();
            }
            for(int i=1;i<=100;i++){
                System.out.println(Thread.currentThread().getName()+":"+i);
            }
        }
        
        
    }
    TestThreadMethod
    package com.btp.t4.多线程;
    /*
     * 线程通信:如下的三个关键字使用的话,都得在同步代码块和同步方法中
     * wait():一旦一个线程执行到wait(),就释放当前的锁
     * notify()/notifyAll():唤醒wait()的一个/所有的线程
     * 使用两个线程打印1-100,线程1,线程2交替打印
     */
    public class TestCommunication {
        public static void main(String[] args){
            PrintNum p=new PrintNum();
            new Thread(p).start();
            new Thread(p).start();
        
        }
    }
    class PrintNum implements Runnable{
        int  num=1;
        @Override
        public void run() {
            // TODO 自动生成的方法存根
            while(true){
                synchronized(this){
                    notify();//唤醒另外一个线程,但由于此时锁是本线程掌握的,所以还是本线程先执行
                    if(num<=100){
                        try {
                            Thread.currentThread().sleep(10);
                        } catch (InterruptedException e) {
                            // TODO 自动生成的 catch 块
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName()+":"+num);
                        num++;
                    }
                    try {
                        wait();//释放本线程的锁和资源,使另外一个线程可以获得
                    } catch (InterruptedException e) {
                        // TODO 自动生成的 catch 块
                        e.printStackTrace();
                    }
                }
            }
        }
        
    }
    TestCommunication
    package com.btp.t4.多线程;
    
    public class Practice {
    
        public static void main(String[] args) {
            //1.继承的方式
    //        Account ac=new Account(0);
    //        Customer c1=new Customer(ac);
    //        Customer c2=new Customer(ac);
    //        c1.setName("账户1");
    //        c2.setName("账户2");
    //        c1.start();
    //        c2.start();
            //2.实现的方式
            Account ac1=new Account(0);
            Customer1 cs=new Customer1(ac1);
            new Thread(cs).start();
            new Thread(cs).start();
        }
    
    }
    
    
    class Account{
        private int money;
    
        public int getMoney() {
            return money;
        }
    
        public void setMoney(int money) {
            this.money = money;
        }
    
        @Override
        public String toString() {
            return "Account [money=" + money + "]";
        }
    
        public Account(int money) {
            super();
            this.money = money;
        }
    
        public Account() {
            super();
        }
        public void addMoney(int money){
            this.money+=money;
        }
        
    }
    //继承的方式
    class Customer extends Thread{
        Account ac=null;
    
        public Account getAc() {
            return ac;
        }
    
        public void setAc(Account ac) {
            this.ac = ac;
        }
    
        @Override
        public String toString() {
            return "Customer [ac=" + ac + "]";
        }
    
        public Customer(Account ac) {
            super();
            this.ac = ac;
        }
    
        public Customer() {
            super();
        }
        public void addMoney(int money){
            synchronized(Customer.class){
            for(int i=0;i<3;i++){
            try {
                Thread.currentThread().sleep(1000);
            } catch (InterruptedException e) {
                // TODO 自动生成的 catch 块
                e.printStackTrace();
            }
            this.ac.addMoney(money);
            System.out.println(Thread.currentThread().getName()+":"+ac.getMoney());
            }
            }
        }
        public void run(){
            addMoney(1000);
        }    
    }
    
    
    //实现的方式
    class Customer1 implements Runnable{
        Account ac=null;
        
        public Account getAc() {
            return ac;
        }
    
        public void setAc(Account ac) {
            this.ac = ac;
        }
    
        @Override
        public String toString() {
            return "Customer1 [ac=" + ac + "]";
        }
    
        public Customer1(Account ac) {
            super();
            this.ac = ac;
        }
    
        public Customer1() {
            super();
            // TODO 自动生成的构造函数存根
        }
        public synchronized void addMoney(int money){
            for(int i=0;i<3;i++){
            try {
                Thread.currentThread().sleep(1000);
            } catch (InterruptedException e) {
                // TODO 自动生成的 catch 块
                e.printStackTrace();
            }
            this.ac.addMoney(money);
            System.out.println(Thread.currentThread().getName()+":"+ac.getMoney());
            }
        }
        @Override
        public void run() {
            addMoney(1000);
        }
        
    }
    Practice
    package com.btp.t4.多线程;
    /*
     * 死锁
     */
    public class TestDeadLock {
        static StringBuffer sb1=new StringBuffer();
        static StringBuffer sb2=new StringBuffer();
        public static void main(String[] args){
            new Thread(){
                public void run(){
                    synchronized(sb1){
                        try {
                            Thread.currentThread().sleep(100);
                        } catch (InterruptedException e) {
                            // TODO 自动生成的 catch 块
                            e.printStackTrace();
                        }
                        sb2.append("A");
                        synchronized(sb2){
                            sb1.append("B");
                            System.out.println(sb1.toString());
                            System.out.println(sb2.toString());
                        }
                    }
                }
            }.start();
            
            new Thread(){
                public void run(){
                    synchronized(sb2){
                        try {
                            Thread.currentThread().sleep(100);
                        } catch (InterruptedException e) {
                            // TODO 自动生成的 catch 块
                            e.printStackTrace();
                        }
                        sb2.append("C");
                        synchronized(sb1){
                            sb1.append("D");
                            System.out.println(sb1.toString());
                            System.out.println(sb2.toString());
                        }
                    }
                }
            }.start();
        }
        
    }
    TestDeadLock
    package com.btp.t4.多线程;
    /*
     * 关于懒汉式的线程安全问题:使用同步机制
     * 对于一般的方法,使用同步代码块,锁可以考虑使用this
     * 对于静态方法而言,使用当前类本身充当锁:类名.class
     */
    public class TestSingletonSecurity {
    
        public static void main(String[] args) {
            Singleton s=Singleton.returnSingleton();
            Singleton s1=Singleton.returnSingleton();
            System.out.println(s==s1);
        }
    
    }
    
    class Singleton
    {
        private Singleton(){
            
        }
        private static Singleton sl=null;
        
        public static Singleton returnSingleton(){
            if(sl==null){
            synchronized(Singleton.class){//使用类本身作为锁,其实还是一个对象 Class cl=Singleton.class;
                
            if(sl==null)sl=new Singleton();//如果一个线程进来,发现s1==null,然后还没有创建对象,就挂起了
                                           //这时候又有一个线程进来,发现此时s1还是null,创建对象,然后这时候
                                           //原先那个线程挂起状态结束,运行,也创建了一个对象,这时候就有2个对象
                                           //就是线程不安全的
            }
            }
            return sl;
        }
    }
    TestSingletonSecurity
    package com.btp.t4.多线程;
    /*
     * 生产者/消费者的问题
     * 生产者将产品交给店员,而消费者从店员处拿走产品。店员一次只能持有固定数量的产品,如果生产者
     * 试图生产更多的产品,店员会叫停一下,如果店中有空位了再通知生产者继续生产,如果店中没有产品了,
     * 店员会告诉消费者等一下,如果店中有产品了再通知消费者来取走产品。
     * 
     * 分析
     * 1.是否涉及到多线程的问题?是!生产者和消费者
     * 2.是否涉及到共享数据?有,即为产品数量
     * 3.是否涉及到线程的通信?有。
     */
    public class TestProduceConsume {
    
        public static void main(String[] args) {
            Clerk clerk=new Clerk(0);
            Producter p=new Producter(clerk);
            Consumer c=new Consumer(clerk);
            Thread p1=new Thread(p);
            p1.setName("Producter1");
            p1.start();
    //        
    //        Thread p2=new Thread(p);
    //        p2.setName("Producter2");
    //        p2.start();
            
            Thread c1=new Thread(c);
            c1.setName("Consumer1");
            c1.start();
            
            Thread c2=new Thread(c);
            c2.setName("Consumer2");
            c2.start();
            
        }
    
    }
    
    class Producter implements Runnable{//生产者
        Clerk clerk;
        
        public Producter(Clerk clerk) {
        super();
        this.clerk = clerk;
    }
    
        @Override
        public void run() {
            System.out.println("生产者开始生产!");
            while(true){
            clerk.addProduct();
            }
        }
        
    }
    
    class Consumer implements Runnable{//消费者
        Clerk clerk;
        
        public Consumer(Clerk clerk) {
        super();
        this.clerk = clerk;
    }
    
        @Override
        public void run() {
            System.out.println("消费者开始消费!");
            while(true){
            clerk.consumeProduct();
            }
        }
        
    }
    
    class Clerk{//店员
        int product;
        
        public Clerk(int product) {
        super();
        this.product = product;
    }
    
        public static int PRODUCT=20;//最多持有产品数量 
        public synchronized void addProduct(){//生产产品
            if(product>=PRODUCT){
                try {
                    wait();
                } catch (InterruptedException e) {
                    // TODO 自动生成的 catch 块
                    e.printStackTrace();
                }
            }else{
                product++;
                System.out.println(Thread.currentThread().getName()+"生产了第"+product+"件产品");
                notifyAll();
            }
        }
        
        public synchronized void consumeProduct(){//消费产品
            if(product<=0){
                try {
                    wait();
                } catch (InterruptedException e) {
                    // TODO 自动生成的 catch 块
                    e.printStackTrace();
                }
            }else{
                product--;
                System.out.println(Thread.currentThread().getName()+"消费了第"+product+"件产品");
                notifyAll();
            }
        }
    }
    TestProduceConsume
  • 相关阅读:
    Windows Azure 架构指南 – 第 1卷 发布
    SQL Azure 入门教学(一):SQL Azure之初体验
    WPC大会新动态: Windows Azure Platform Appliance发布
    Windows Azure AppFabric 入门教学(七):多播(Multicast)
    PHP on Windows Azure 入门教学系列(一):在Windows Azure内运行PHP应用
    SQL Azure SU3 现已在全球6座数据中心开始启用
    WPC大会新动态:合作伙伴采纳Windows Azure
    时间的运算
    把字符串复制到剪贴板
    常用的表格效果
  • 原文地址:https://www.cnblogs.com/a842297171/p/5199765.html
Copyright © 2020-2023  润新知