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();

    }
}
时间: 2024-10-03 13:39:53

Java学习-第四天的相关文章

从.Net到Java学习第四篇——spring boot+redis

从.Net到Java学习第一篇——开篇 从.Net到Java学习第二篇——IDEA and start spring boot 从.Net到Java学习第三篇——spring boot+mybatis+mysql 接上一篇,本篇使用到的框架redis.FastJSON. 环境准备 安装redis,下图是我本机的redis绿色版,你可以网上自行下载安装,如果不知道如何怎么操作,可以移步到我的另一篇文章:ASP.NET Redis 开发 以管理员身份打开CMD窗口: C:\Users\zouqj>e

Java学习笔记四(代码块 )

1 代码块的分类:java中的代码块是指使用{}括起来的一段代码,根据位置不同可以分为四种: 普通代码块 构造快 静态代码块 同步代码块 今天主要学习前三种代码块,同步代码块在学习到多线程部分的时候再加学习. 2 普通代码块:直接定义在方法中的代码块,如下: public class CodeSpace { public static void main(String args[]){ { int x = 30; System.out.println("普通代码块x="+x); } /

JAVA学习第四十七课 — IO流(一):文件的读写

输入流和输出流相对于内存 将外部设备的数据读取到内存中:输入 将内存中的数据写入外部设备中:输出 IO流常用基类 字节流的抽象基类:InputStream,OutputStream 字符的抽象基类:Reader,Writer PS:由这四个流派生出的子类都是以父类名作为后缀名 如:InputStream的派生类FileInputStream,Reader的派生类FileReader PS:如果是文字形式的数据应该优先考虑字符流,且将数据从内存写到硬盘上应该是Writer FileWriter类

java学习 第四天 数组

数组是有序数据的集合,数组中的每个元素具有相同的数组名和下标来唯一地确定数组中的元素. §5.1一维数组 一.一维数组的定义 type arrayName[]; 其中类型(type)可以为Java中任意的数据类型,包括简单类型组合类型,数组名arrayName为一个合法的标识符,[]指明该变量是一个数组类型变量.例如: int intArray[]; 声明了一个整型数组,数组中的每个元素为整型数据.与C.C++不同,Java在数组的定义中并不为数组元素分配内存,因此[]中不用指出数组中元素个数,

java学习笔记四:static的几个角落及小谈多态

最近有点事情,没有及时更新笔记,学习不可弃,总结一下最近的学习,其中重点是static的一些应用,多态是一种设计理念,了解较容易,想如火纯清的确不是一件容易的事情. 对于static,主要有两点是我所学习的. 1.首先简单的介绍一下static的定义.static是静态的意思,就是说这个类变量或者类方法不需要实例化就可以使用.使用static的变量是类变量,也成为静态域(static field).这些是static的基本语义,了解了这些,继续向下看. java核心技术(卷一)对于静态有这样一段

JAVA学习第四十二课 — 泛型(二)—泛型接口&amp;&amp;通配符应用

一.泛型接口 interface Inter<T>{ public void show(T t); } class InterImple implements Inter<String>{//知道是字符串类型 public void show(String str){ System.out.println("show "+str); } } class InterImple_2<Q> implements Inter<Q>{//不知道是什

JAVA学习笔记(四十七)- 事件监听

定义ActionListener接口的实现类实现事件监听 import java.awt.Button; import java.awt.Frame; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; /* * 事件监听 */ public class Te

JAVA学习笔记(四十九)- Swing相关组件

JFrame组件 import java.awt.Color; import javax.swing.JFrame; import javax.swing.JPanel; /* * Swing是在AWT基础上的扩展 * javax.swing包及其扩展包,组件的命名多以J开关 * * JFrame组件 */ public class Test08 { public static void main(String[] args) { JFrame frame=new JFrame("我的窗体&qu

JAVA学习第四十九课 — IO流(三):缓冲区2 &amp; 装饰设计模式

一.模拟BufferedReader 自定义MyBuffereaReader 对于缓冲区而言,里面其实就是封装一个数组,对外提供方法对数组的操作,这些方法最终操作的都是数组的角标 原理:从源中取出数据存入缓冲区,再从缓冲区不断的取出数据,取完后,继续从源中继续取数据,进缓冲区,直至源中的数据取完,用-1做为结束标记 import java.io.*; class MyBufferedReader { private FileReader fr; //定义数组作为缓冲区 private char[

java学习(四)代码的设计

一.目的 1.为了使程序员编写的代码更加的简洁,使人阅读起来更加流畅 2.将运算代码与界面代码完全分离开来,利于团队开发,提高团队之间的工作效率 3. 在很短的时间内可以替换整个站点的外观: 4.使程序员可以抽象编程,而无须接触HTML代码: 5.可以重复利用以前的模板. 二.示例 引用前一篇的记忆曲线的JSP文件 1.未进行分离的代码 1 <%@ page language="java" contentType="text/html; charset=UTF-8&qu