首页 > 代码库 > Java学习-第四天

Java学习-第四天

Day11/*进程:是一个正在被执行中的程序。    每一个进程执行都有一个执行顺序,该顺序是一个执行路径,或者叫一个控制单元。线程:就是进程中的一个独立完成控制单元。    线程在控制着进程的执行。一个进程中至少有一个线程。创建线程的第一种方式, 继承Thread类步骤:1.定义类继承Thread类2.复写Thread类中的run方法,(目的是将自定义代码存储在run方法中,让线程运行。)3.实例化定义的类,调用start方法,start方法有两个作用,1)启动线程 2)调用run方法为什么覆盖run方法呢Thread类用于描述线程。该类定义了一个功能,用于存储线程要运行而定代码,该存储功能就是run方法。也就是说Thread类中的run方法,用于存储线程运行的代码。*/class D11Demo extends Thread{    public void run()    {        for (int i=0;i<100;i++ )        {            System.out.println("---demo run---"+i);        }    }}class  D11TheradDemo{    public static void main(String[] args)     {                Demo d = new Demo();        d.start();//开启线程并执行该线程的run方法。        d.run();//仅仅是对象的函数调用,而线程创建了,并没有运行。        //        for (int i=0;i<100;i++ )        {            System.out.println("---mian run---"+i);        }    }}/*练习: 创建两个线程和主线程交替运行通过 this.getName()或Thread.currentThread() 方法可以获取线程名称*/class D11Test1 extends Thread{    public void run()    {        for (int i=0;i<30;i++ )        {            System.out.println(getName()+"---run---"+i);        }    }}class D11Test2 extends Thread{    public void run()    {        for (int i=0;i<30;i++ )        {            System.out.println(getName()+"---run---"+i);        }    }}class D11Test3 extends Thread{    public void run()    {        for (int i=0;i<30;i++ )        {            System.out.println(getName()+"---run---"+i);        }    }}class  D11TheradTestDemo{    public static void main(String[] args)     {                D11Test1 t1 = new D11Test1();        t1.start();         D11Test2 t2 = new D11Test2();        t2.start();         D11Test3 t3 = new D11Test3();        t3.start();                 for (int i=0;i<30;i++ )        {            System.out.println("---mian run---"+i);        }    }}/*练习2需求:简单的买票程序。多个窗口同时买票。创建线程的第二种方法,实现 Runnable 接口步骤1.定义类实现Runnable接口2.覆盖Runnable接口中的run方法。将线程要运行的代码存放在run方法中)3.通过Thread类建立线程对象。4.将Runnable接口的子类对象作为实际参数给Thread类的构造函数。    自定义的run方法所属的对象时Runnable接口的子类对象,所以要让线程调用指定对象的run方法,就必须明确该run方法的对象。5.调用Thread类的start方法开启线程并调用Runnable接口子类的run方法。两种方式的区别:Runnable方式:    1.避免的单继承的局限性,在定义线程是建议使用该方式。    2.线程代码存在Runnable子类的run方法中继承Thread方式:        1.有局限性,因为Java的单继承特性如果继承可Thread类限制了继承其他类。    2.线程带代码存放在Thread子类的run方法中。*/class D11Ticket implements  Runnable//Thread{    private int tick = 100;        public void run()    {        while(true)        {            if(tick >0)            {                /*                try                {                    Thread.sleep(10);                }                catch (Exception e)                {                }                */                /*                通过上面代码 Thread.sleep(10); 分析发现 打印出 0 -1 -2 等错票                多线程的运行出现的安全问题。                问题的原因:                    当多条语句在操作同一个线程共享数据时,                    一个线程对多条语句执行了一部分,还没有执行完毕时,                    另一个线程参与进来执行,导致共享数据的错误。                解决方法:                    对于多条操作的共享数据的语句,只能让一个线程都执行完毕。                    在一个线程执行过程中,其他线程不可以参与执行。                                Java对于多线程的安全问题提供了一个同步代码块用于解决这种问题。                                格式如下:                synchronized(对象)                {                }                                    */                System.out.println(Thread.currentThread().getName()+" Sale :"+ tick --);            }        }    }}class D11TicketDemo{    public static void main(String[] args)     {        D11Ticket t1 = new D11Ticket();        new Thread(t1).start();        new Thread(t1).start();        new Thread(t1).start();        new Thread(t1).start();            }}/*Java对于多线程的安全问题提供了一个同步代码块用于解决这种问题。                                格式如下:                synchronized(对象)                {                }对象如同锁,持有锁的线程可以再同步中执行,没有持有锁的线程即使获取到CPU的执行权,也进不去,因为没有锁。同步的前提:1.必须要有两个或者两个以上的线程。2.必须是多个线程使用同一个锁。同步的利弊:利:保证只用一个线程在执行,解决了多线程中多条语句在操作同一个线程共享数据时的安全问题。弊:多个线程都需要判断锁,较为消耗资源。*/class D11Ticket2 implements  Runnable//Thread{    private int tick = 100;    Object obj = new Object();        public void run()    {        while(true)        {            synchronized(obj)            {                if(tick >0)                {                    try                    {                        Thread.sleep(10);                    }                    catch (Exception e)                    {                    }                    //                    System.out.println(Thread.currentThread().getName()+" Sale :"+ tick --);                }            }        }    }}class D11TicketDemo2{    public static void main(String[] args)     {        D11Ticket2 t1 = new D11Ticket2();        new Thread(t1).start();        new Thread(t1).start();        new Thread(t1).start();        new Thread(t1).start();            }}/*练习3需求:银行有一个金库有两个存户分别存300斤黄金,每次存100斤,存3次。目的: 该程序是否有安全问题,如果有,如何解决?如何找问题:1.明确哪些代码是多线程执行代码。2.明确哪些是共享数据。3.明确多线程运行代码中哪些语句是操作共享数据的。*/class  D11Bank{    private int sum;        //同步函数也可以解决这种问题。    public synchronized void add(int n)    {        sum +=n;        //        try{Thread.sleep(1000);}catch (Exception e){}        System.out.println("sum="+ sum);    }}class D11Cus implements Runnable{    private D11Bank b = new D11Bank();    public void run()    {        for(int i =0; i<3 ;i++ )        {            b.add(100);        }    }}class D11BankDemo{    public static void main(String[] args)     {        D11Cus c = new D11Cus();        //        Thread t1 =    new Thread(c);        Thread t2 = new Thread(c);        //        t1.start();        t2.start();    }}/*同步函数用的是哪一个锁呢?    函数需要被对象调用,那么函数都有一个所属对象引用,就是this。    所以同步函数使用的锁是this        下面通过该程序进行验证:        使用线程来卖票    一个线程在同步代码中,一个线程在同步函数中。    都在执行卖票动作*/class D11Ticket3 implements  Runnable//Thread{    private int tick = 100;    Object obj = new Object();        boolean flag = true;    public void run()    {        if(flag)        {            while(true)            {                synchronized(this)                {                    if(tick >0)                    {                        try{Thread.sleep(10);}catch (Exception e){}                        //                        System.out.println(Thread.currentThread().getName()+" code Sale :"+ tick --);                    }                }            }        }        else        {            while(true)            {                show();            }        }    }    public synchronized void show()    {        if(tick >0)        {            try{Thread.sleep(10);}catch (Exception e){}            //            System.out.println(Thread.currentThread().getName()+" function  Sale :"+ tick --);        }            }}class D11TicketDemo3{    public static void main(String[] args)     {        D11Ticket3 t = new D11Ticket3();        Thread t1 =    new Thread(t);        Thread t2 = new Thread(t);        //        t1.start();        try{Thread.sleep(10);}catch (Exception e){}        t.flag =false;        t2.start();            }}/*如果同步函数被static修饰后,使用的锁是什么呢?静态进内存时,内存中没有本类对象,但是一定有该类对应的字节码文件对象。类名.class 该对象的类型是Class所以静态的同步方法,使用的锁是该方法所在类的字节码文件对象。 类名.class*/class D11Ticket4 implements  Runnable//Thread{    private static int tick = 100;    Object obj = new Object();        boolean flag = true;    public void run()    {        if(flag)        {            while(true)            {                //synchronized(obj)                synchronized(D11Ticket4.class)                {                    if(tick >0)                    {                        try{Thread.sleep(20);}catch (Exception e){}                        //                        System.out.println(Thread.currentThread().getName()+" code Sale :"+ tick --);                    }                }            }        }        else        {            while(true)            {                show();            }        }    }    public static synchronized void show()    {        if(tick >0)        {            try{Thread.sleep(10);}catch (Exception e){}            //            System.out.println(Thread.currentThread().getName()+" function  Sale :"+ tick --);        }            }}class D11TicketDemo4{    public static void main(String[] args)     {        D11Ticket4 t = new D11Ticket4();        Thread t1 =    new Thread(t);        Thread t2 = new Thread(t);        //        t1.start();        try{Thread.sleep(10);}catch (Exception e){}        t.flag =false;        t2.start();            }}/*重提 单例设计模式*//*//饿汉式class Single{    private static final  Single s =new Single();    private Single();    public static Single getInstance()    {        return s;    }}*///懒汉式class D11Single{    private static D11Single s =null;    private D11Single(){}    public static D11Single getInstance()    {            //双重判断        if(s == null)        {            synchronized(D11Single.class)            {                if(s == null)                {                    s = new D11Single();                }            }        }        return s;    }}/*死锁同步中嵌套同步*/class D11Ticket5 implements  Runnable//Thread{    private static int tick = 100;    Object obj = new Object();        boolean flag = true;    public void run()    {        if(flag)        {            while(true)            {                synchronized(D11Ticket4.class)                {                    show();                }            }        }        else        {            while(true)            {                show();            }        }    }    public static synchronized void show()    {        synchronized(D11Ticket4.class)        {            if(tick >0)            {                try{Thread.sleep(20);}catch (Exception e){}                //                System.out.println(Thread.currentThread().getName()+" code Sale :"+ tick --);            }        }        }}class D11TicketDemo5{    public static void main(String[] args)     {        D11Ticket5 t = new D11Ticket5();        Thread t1 =    new Thread(t);        Thread t2 = new Thread(t);        //        t1.start();        try{Thread.sleep(10);}catch (Exception e){}        t.flag =false;        t2.start();            }}class D11TestLock implements Runnable{    private boolean flag;    D11TestLock(boolean flag)    {        this.flag = flag;    }    public void run()    {        if(flag)        {            synchronized(D11MyLock.locka)            {                System.out.println("if locka");                synchronized(D11MyLock.lockb)                {                    System.out.println("if lockb");                }            }        }        else        {            System.out.println("else lockb");            synchronized(D11MyLock.lockb)            {                synchronized(D11MyLock.locka)                {                    System.out.println("else locka");                }            }        }    }}class  D11MyLock{    static Object locka =  new Object();    static Object lockb =  new Object();}class D11DeadLockTest{        public static void main(String[] args)     {        Thread t1 =    new Thread(new D11TestLock(true));        Thread t2 = new Thread(new D11TestLock(false));        //        t1.start();        t2.start();    }}Day12/*线程间通讯其实就是多个线程在操作同一个资源但是操作的动作不同wait();线程存储在线程池中notify();唤醒线程池中的线程,通常唤醒顶部的线程。notifyAll();;唤醒线程池中所有的线程这些作线程的方法要使用在同步中,因为要对持有监视器(锁)的线程操作。所以要使用在同步中,因为只有同步才具有锁。为什么这些操作线程的方法要定义在Object类中呢?因为这些方法在操作同步中线程时,都必须要标识它们所操作线程只有的锁。只有同一个锁上的被wait()的线程,才可以被同一个锁上的notify()唤醒线程,不可以对不同锁中的线程进行唤醒。(也就是说,等待和唤醒线程的必须是同一个锁。)因为锁可以使任意对象,所以可以被任意对象调用的方法只能有Object,所以定义在Object类中。*/import java.util.concurrent.locks.*;class D12Res{    String name;    String sex;    boolean flag = false;}class D12Input implements Runnable{    private D12Res r;    D12Input(D12Res r)    {        this.r = r ;    }    public void run()    {        int i=0;        while(true)        {            synchronized(r)            {                if(r.flag)                    try{r.wait();}catch (Exception e){}                                    if(i%2==0)                {                    r.name ="tom";                    r.sex = "man";                }                else                {                    r.name ="赫尔";                    r.sex = "女";                }                i++;                r.flag =true;                //唤醒OutPut                r.notify();            }                    }    }}class D12Output implements Runnable{    private D12Res r;    D12Output(D12Res r)    {        this.r = r ;    }    public void run()    {        while(true)        {            synchronized(r)            {                if(!r.flag)                    try{r.wait();}catch (Exception e){}                System.out.println(r.name+"   "+r.sex);                //                r.flag =false;                r.notify();            }        }    }}class  D12InPutAndOutPutDemom{    public static void main(String[] args)     {        D12Res r = new D12Res();        D12Input in = new D12Input(r);        D12Output out = new D12Output(r);        Thread t1 = new Thread(in);        Thread t2 = new Thread(out);        t1.start();        t2.start();    }}/*    改进D12Res*/class D12Res2{    private String name;    private String sex;    private boolean flag = false;    public synchronized void set(String name, String  sex )    {        if(flag)            try{this.wait();}catch (Exception e){}        this.name = name ;        this.sex = sex;        flag = true;        this.notify();    }    public synchronized void out()    {        if(!flag)            try{this.wait();}catch (Exception e){}        System.out.println(this.name+"   "+this.sex);        flag = false;        this.notify();    }}class D12Input2 implements Runnable{    private D12Res2 r;    D12Input2(D12Res2 r)    {        this.r = r ;    }    public void run()    {        int i=0;        while(true)        {            if(i%2==0)                r.set("tom" ,"man");            else                r.set("赫尔" ,"女");            i++;                }    }}class D12Output2 implements Runnable{    private D12Res2 r;    D12Output2(D12Res2 r)    {        this.r = r ;    }    public void run()    {        while(true)        {            r.out();        }    }}class  D12InPutAndOutPutDemom2{    public static void main(String[] args)     {        D12Res2 r = new D12Res2();        new Thread(new D12Input2(r)).start();        new Thread(new D12Output2(r)).start();    }}class D12Resource{    private String name;    private int num =1;    private Boolean flag = false;    public synchronized void set(String name)    {        if(flag)            try{this.wait();}catch (Exception e){}                this.name = name + "..." + num++;                System.out.println(Thread.currentThread().getName()+"...生产者..."+this.name);        flag =true;        this.notify();    }    public synchronized void out()    {        if(!flag)            try{this.wait();}catch (Exception e){}                System.out.println(Thread.currentThread().getName()+".........消费者........."+this.name);        flag =false;        this.notify();    }}class D12Producer implements Runnable{    private D12Resource res;        D12Producer(D12Resource res)    {        this.res = res;    }    public void run()    {        while(true)            res.set("商品");    }}class D12Consumer implements Runnable{    private D12Resource res;        D12Consumer(D12Resource res)    {        this.res = res;    }    public void run()    {        while(true)            res.out();    }}class D12ResourceDemo{    public static void main(String[] args)     {        D12Resource r = new D12Resource();        D12Producer pro = new D12Producer(r);        D12Consumer con = new D12Consumer(r);                Thread t1 = new Thread(pro);        Thread t2 = new Thread(pro);        Thread t3 = new Thread(pro);        Thread t4 = new Thread(pro);        Thread t5 = new Thread(con);        Thread t6 = new Thread(con);        Thread t7 = new Thread(con);        Thread t8 = new Thread(con);        t1.start();        t2.start();        t3.start();        t4.start();        t5.start();        t6.start();        t7.start();        t8.start();        /*        运行后会发现存在生产一个消费多个或生产多个消费单个(有些生产被无视)的异常。        运行异常如下:                Thread-2...生产者...商品...123        Thread-3...生产者...商品...133        Thread-4.........消费者.........商品...133        Thread-2...生产者...商品...134        Thread-4.........消费者.........商品...134        ...        ...        ...        ...        ...        Thread-0...生产者...商品...1453        Thread-4.........消费者.........商品...1453        Thread-1...生产者...商品...1454        Thread-2...生产者...商品...1455        Thread-5.........消费者.........商品...1455        Thread-6.........消费者.........商品...1455        Thread-7.........消费者.........商品...1455        Thread-8.........消费者.........商品...1455        E:\ProgramCode\Java\JAVA毕向东>        */    }}/*运行后会发现存在消费多个或生产多个的异常。产生问题的原因是:线程在被唤醒的时候没有判断自己有没有是否具备执行生产或消费。从而导致消费多个或生产多个。即生产线程被生产线程唤醒,其余消费被等待的时候,唤醒的生产线程所做的生产会覆盖前一个生产线程的生产,这样大的生产是不合法的。解决办法:线程被唤醒后,判断是否具备执行。(if 改为 while)不过执行到一定时间后,容易出现只唤醒本方线程的情况,导致程序中的所有线程都处于等待状态。解决办法: notify 改为 notifyAll这样就可以解决这个问题了。对于多个生产者和消费者适用于这样的方法。为什么定义while判断标记?因为让被唤醒的线程再一次判断标记,防止出错。为什么定义为notifyAll?1.因为需要唤醒对方线程2.因为只用notify,容易出现只唤醒本方线程的情况,导致程序中的所有线程都等待。*/class D12Resource2{    private String name;    private int num =1;    private Boolean flag = false;    public synchronized void set(String name)    {        while(flag)            try{this.wait();}catch (Exception e){}                this.name = name + "..." + num++;                System.out.println(Thread.currentThread().getName()+"...生产者..."+this.name);        flag =true;        this.notifyAll();    }    public synchronized void out()    {        while(!flag)            try{this.wait();}catch (Exception e){}                System.out.println(Thread.currentThread().getName()+".........消费者........."+this.name);        flag =false;        this.notifyAll();    }}class D12Producer2 implements Runnable{    private D12Resource2 res;        D12Producer2(D12Resource2 res)    {        this.res = res;    }    public void run()    {        while(true)            res.set("商品");    }}class D12Consumer2 implements Runnable{    private D12Resource2 res;        D12Consumer2(D12Resource2 res)    {        this.res = res;    }    public void run()    {        while(true)            res.out();    }}class D12ResourceDemo2{    public static void main(String[] args)     {        D12Resource2 r = new D12Resource2();        D12Producer2 pro = new D12Producer2(r);        D12Consumer2 con = new D12Consumer2(r);                Thread t1 = new Thread(pro);        Thread t2 = new Thread(pro);        Thread t3 = new Thread(pro);        Thread t4 = new Thread(pro);        Thread t5 = new Thread(con);        Thread t6 = new Thread(con);        Thread t7 = new Thread(con);        Thread t8 = new Thread(con);        t1.start();        t2.start();        t3.start();        t4.start();        t5.start();        t6.start();        t7.start();        t8.start();    }}/*JDK5.0升级 改版生产者消费者换型*/class D12Resource3{    private String name;    private int num =1;    private Boolean flag = false;    //    private Lock lock = new ReentrantLock();    private Condition condition = lock.newCondition();        public void set(String name) throws InterruptedException    {        lock.lock();        try        {            while(flag)            condition.await();            this.name = name + "..." + num++;                    System.out.println(Thread.currentThread().getName()+"...生产者..."+this.name);            flag =true;            condition.signalAll();            }                finally        {            lock.unlock();        }    }    public void out() throws InterruptedException    {            lock.lock();        try        {            while(!flag)                condition.await();            System.out.println(Thread.currentThread().getName()+".........消费者........."+this.name);            flag =false;            condition.signalAll();            }        finally        {            lock.unlock();        }    }}class D12Producer3 implements Runnable{    private D12Resource3 res;        D12Producer3(D12Resource3 res)    {        this.res = res;    }    public void run()    {        while(true)        {            try            {                res.set("商品");            }            catch (InterruptedException e)            {            }        }    }}class D12Consumer3 implements Runnable{    private D12Resource3 res;        D12Consumer3(D12Resource3 res)    {        this.res = res;    }    public void run()    {        while(true)        {            try            {                res.out();            }            catch (InterruptedException e)            {            }        }    }}class D12ResourceDemo3{    public static void main(String[] args)     {        D12Resource3 r = new D12Resource3();        D12Producer3 pro = new D12Producer3(r);        D12Consumer3 con = new D12Consumer3(r);                Thread t1 = new Thread(pro);        Thread t2 = new Thread(pro);        Thread t3 = new Thread(pro);        Thread t4 = new Thread(pro);        Thread t5 = new Thread(con);        Thread t6 = new Thread(con);        Thread t7 = new Thread(con);        Thread t8 = new Thread(con);        t1.start();        t2.start();        t3.start();        t4.start();        t5.start();        t6.start();        t7.start();        t8.start();    }}/*改进升级版生产者消费者定义一两个Condition:condition_pro condition_con生产者线程等待,唤醒消费者等待线程消费者线程等待,换型生产者等待线程即本方线程只唤醒对方线程的操作。JDK1.5 中提供了多线程的升级解决方案。1.将同步 synchronized 替换为 Lock 操作2.将Object中的 wait,notify,notifyAll 替换为condiction 对象,该对象可以对 Lock锁 进行获取*/class D12Resource4{    private String name;    private int num =1;    private Boolean flag = false;    //    private Lock lock = new ReentrantLock();    private Condition condition_pro = lock.newCondition();    private Condition condition_con = lock.newCondition();        public void set(String name) throws InterruptedException    {        lock.lock();        try        {            while(flag)            condition_pro.await();            this.name = name + "..." + num++;                    System.out.println(Thread.currentThread().getName()+"...生产者..."+this.name);            flag =true;            condition_con.signalAll();            }                finally        {            lock.unlock();        }    }    public void out() throws InterruptedException    {            lock.lock();        try        {            while(!flag)                condition_con.await();            System.out.println(Thread.currentThread().getName()+".........消费者........."+this.name);            flag =false;            condition_pro.signalAll();            }        finally        {            lock.unlock();        }    }}class D12Producer4 implements Runnable{    private D12Resource4 res;        D12Producer4(D12Resource4 res)    {        this.res = res;    }    public void run()    {        while(true)        {            try            {                res.set("商品");            }            catch (InterruptedException e)            {            }        }    }}class D12Consumer4 implements Runnable{    private D12Resource4 res;        D12Consumer4(D12Resource4 res)    {        this.res = res;    }    public void run()    {        while(true)        {            try            {                res.out();            }            catch (InterruptedException e)            {            }        }    }}class D12ResourceDemo4{    public static void main(String[] args)     {        D12Resource4 r = new D12Resource4();        D12Producer4 pro = new D12Producer4(r);        D12Consumer4 con = new D12Consumer4(r);                Thread t1 = new Thread(pro);        Thread t2 = new Thread(pro);        Thread t3 = new Thread(pro);        Thread t4 = new Thread(pro);        Thread t5 = new Thread(con);        Thread t6 = new Thread(con);        Thread t7 = new Thread(con);        Thread t8 = new Thread(con);        t1.start();        t2.start();        t3.start();        t4.start();        t5.start();        t6.start();        t7.start();        t8.start();    }}

 

Java学习-第四天