Java第20天~第21天/12.2~12.3

来源:互联网 发布:linux ssh2 编辑:程序博客网 时间:2024/05/24 04:45

day20

一、多线程实现的第一种方式:继承Thread类

1、多线程的实现方式一:继承Thread类
* 1)自定一个类:MyThread 继承自Thread类
* 2)在MyThread类中重写Thread类中的run()
* 3)在主线程中,创建该类的实例对象,启动线程

package org.westos_02_实现多线程第一种方式_继承Thread;/** * 多线程程序实现方式1: *      1)自定一个类:MyThread 继承自Thread类 *      2)在MyThread类中重写Thread类中的run() *      3)在主线程中,创建该类的实例对象,启动线程 * @author 小鑫 */public class ThreadDemo {    public static void main(String[] args) {        //创建该线程的实例对象        MyThread t1 = new MyThread();        //启动线程        //t.run();        //启动线程不是调用run()方法,run()方法只是一个普通的方法,并不会出现线程随机性        //启动线程用的是start()方法,通过JVM调用线程中的run()来进行多个线程抢占cpu执行权        t1.start();        //t.start();//java.lang.IllegalThreadStateException        //同一个对象线程只能启动一次,第二次报异常:非法线程状态异常        MyThread t2 = new MyThread();        t2.start();    }}class MyThread extends Thread{    @Override    public void run() {        for (int x = 0; x < 100; x++) {            System.out.println("hello" + x);        }    }}

这里写图片描述
2、获取多线程名称

package org.westos_03_获取多线程名称;/** * public final String getName()返回该线程的名称。 * public final void setName(String name)改变线程名称,使之与参数 name 相同。  * public static Thread currentThread():表示正在运行的线程 * @author 小鑫 * */public class ThreadDemo {    public static void main(String[] args) {        //无参构造形式        //wuCan();        //有参构造        youCan();    }    private static void youCan() {        //有参构造方式        //创建线程类实例        MyThread my1 = new MyThread("王五");        MyThread my2 = new MyThread("赵六");        //启动线程        my1.start();        my2.start();    }    private static void wuCan() {        //创建线程类的实例        //无参构造方式        MyThread my1 = new MyThread();        MyThread my2 = new MyThread();        //设置名称        //public final void setName(String name)        my1.setName("张三");        my1.setName("李四");        //public static Thread currentThread():表示正在运行的线程        //默认所有的子线程的都在主线程中        System.out.println(Thread.currentThread().getName());//main        //分别启动线程        my1.start();        my2.start();    }}class MyThread extends Thread{    //无参构造    public MyThread(){    }    //有参构造    public MyThread(String name){        super(name);    }    @Override    ////my1和my2子线程都会执行这段代码,两个子线程在互相抢占CPU的执行权    public void run() {        for(int x=0;x<100;x++){            System.out.println("hello"+x);        }    }}

3、线程终止
public final void join() throws InterruptedException等待该线程终止。

package org.westos_04_线程终止_线程暂停_线程优先级;/** * public final void join()       throws InterruptedException等待该线程终止。  * 其他线程要等待该线程终止后才能开始运行 * @author 小鑫 */public class JoinDemo {    public static void main(String[] args) {        //无参构造        //创建线程实例对象        MyJoin mj1 = new MyJoin();        MyJoin mj2 = new MyJoin();        MyJoin mj3 = new MyJoin();        //设置名称        mj1.setName("张三");        mj2.setName("李四");        mj3.setName("王五");        //启动线程        mj1.start();        try {            mj1.join();        } catch (InterruptedException e) {            // 中断异常            e.printStackTrace();        }        mj2.start();        mj3.start();    }}class MyJoin extends Thread{    @Override    public void run() {        for(int x=0;x<100;x++){            System.out.println(getName()+":"+x);        }    }}

4、线程的暂停
public static void yield()暂停当前正在执行的线程对象,并执行其他线程。

package org.westos_04_线程终止_线程暂停_线程优先级;/** * public static void yield()暂停当前正在执行的线程对象,并执行其他线程。 * 暂停当前线程执行其他线程,并不保证另一个线程就一定能抢占到CPU的执行权 * 暂停之后,二者重新抢夺CPU执行权 * @author 小鑫 * */public class YieldThreadDemo {    public static void main(String[] args) {        //创建线程实例对象        //无参构造        MyYieldThread my1 = new MyYieldThread();        MyYieldThread my2 = new MyYieldThread();        //设置名称        my1.setName("张三");        my2.setName("李四");        //启动线程        my1.start();        my2.start();    }}class MyYieldThread extends Thread{    @Override    public void run() {        for(int x=0;x<100;x++){            System.out.println(getName()+":"+x);            //public static void yield():暂停当前线程            Thread.yield();        }    }}

5、线程的优先级
public final int getPriority()返回线程的优先级。

package org.westos_04_线程终止_线程暂停_线程优先级;/** * public final int getPriority()返回线程的优先级。  * 默认优先级是5 *  java.lang.Thread         public static final int MAX_PRIORITY 10  :最大优先级         优先级大的抢占到CPU的执行权大,并不代表就一定能抢到,因为线程的执行具有随机性!        public static final int MIN_PRIORITY 1   :最小优先级        public static final int NORM_PRIORITY 5  :默认优先级 * @author 小鑫 * */public class PriorityDemo {    public static void main(String[] args) {        //有参构造        //创建线程实例对象        MyPaiority mp1 = new MyPaiority("刘备");        MyPaiority mp2 = new MyPaiority("关羽");        MyPaiority mp3 = new MyPaiority("张飞");        //获取优先级        //System.out.println(mp1.getPriority());//5        //System.out.println(mp2.getPriority());//5        //System.out.println(mp3.getPriority());//5        //设置优先级        mp1.setPriority(10);        mp3.setPriority(1);        //启动线程        mp1.start();        mp2.start();        mp3.start();    }}class MyPaiority extends Thread{    public MyPaiority() {        super();    }    public MyPaiority(String name) {        super(name);    }    @Override    public void run() {        for(int x=0;x<100;x++){            System.out.println(getName()+":"+x);        }    }}

6、线程睡眠

package org.westos_05_线程睡眠_线程停止_守护线程;import java.util.Date;public class SleepDemo {    public static void main(String[] args) {        //创建线程实例对象        ThreadSleep ts1 = new ThreadSleep();        ThreadSleep ts2 = new ThreadSleep();        ThreadSleep ts3 = new ThreadSleep();        //设置名称        ts1.setName("线程1");        ts2.setName("线程2");        ts3.setName("线程3");        //启动线程        ts1.start();        ts2.start();        ts3.start();    }}class ThreadSleep extends Thread{    @Override    public void run() {        for(int x=1;x<=30;x++){            System.out.println(getName()+":"+x+",日期:"+new Date());            //睡眠1秒            try {                Thread.sleep(1000);            } catch (InterruptedException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }        }    }}

7、停止线程和中断线程
public final void stop():强迫线程停止执行
public void interrupt()中断线程。 表示中断线程一种状态

package org.westos_05_线程睡眠_线程停止_守护线程;import java.util.Date;/** * public final void stop():强迫线程停止执行 * public void interrupt()中断线程。 表示中断线程一种状态 * @author 小鑫 * */public class StopDemo {    public static void main(String[] args) {        //创建线程实例对象        StopThread st = new StopThread();        //启动线程        st.start();        //开始执行Tue Dec 05 20:12:10 CST 2017        //结束执行Tue Dec 05 20:12:15 CST 2017        //三秒睡不醒,停止它        try {            Thread.sleep(3000);            //st.stop();//中间那条线表示过时了            //开始执行Tue Dec 05 20:11:40 CST 2017            st.interrupt();            //开始执行Tue Dec 05 20:12:55 CST 2017            //线程睡着了            //结束执行Tue Dec 05 20:12:58 CST 2017            //能打印线程睡着了,说明走catch语句,即中断try语句        } catch (InterruptedException e) {            e.printStackTrace();        }           }}class StopThread extends Thread{    @Override    public void run() {        System.out.println("开始执行"+new Date());        try {            Thread.sleep(5000);        } catch (InterruptedException e) {            System.out.println("线程睡着了");        }        System.out.println("结束执行"+new Date());    }}

8、守护线程
public final void setDaemon(boolean on) on指定true,就是设置守护线程…
将该线程标记为守护线程或用户线程。

package org.westos_05_线程睡眠_线程停止_守护线程;/** * public final void setDaemon(boolean on)  on指定true,就是设置守护线程... * 将该线程标记为守护线程或用户线程。 * 当正在运行的线程都是守护线程时,Java 虚拟机退出。  * 该方法必须在启动线程前调用。 * jvm自动退出,对于主线程的数据如果直接输出完毕,对于两个守护线程来说不会立即消失,Jvm等会就自动退出. * @author 小鑫 * */public class DemaonDemo {    public static void main(String[] args) {        //创建线程实例对象        MyDemaonThread mt1 = new MyDemaonThread();        MyDemaonThread mt2 = new MyDemaonThread();        //设置名称        mt1.setName("守护1");        mt2.setName("守护2");        //设置守护线程        mt1.setDaemon(true);        mt2.setDaemon(true);        //启动线程        mt1.start();        mt2.start();        //设置被守护线程        Thread.currentThread().setName("被守护线程");        for(int x=0;x<5;x++){            System.out.println(Thread.currentThread().getName()+":"+x);        }    }}class MyDemaonThread extends Thread{    @Override    public void run() {        for(int x=0;x<100;x++){            System.out.println(getName()+":"+x);        }    }}

二、多线程实现的第二种方式:Runnable接口

1、多线程实现的第二种方式:Runnable接口
* 1)自定义一个类MyRunnable,该类实现Runnable接口
* 2)实现该接口中的run()方法
* 3)在主线程中创建该类的实例对象,
* 4)创建Thread类对象,将3)创建的这个对象作为参数进行传递
* 5)分别启动线程

package org.westos_06_实现多线程第二种方式_Runnable接口;/** * 多线程实现的第二种方式:(实际开发中第二种比第一种应用更广泛) *      开发步骤: *  1)自定义一个类MyRunnable,该类实现Runnable接口 *  2)实现该接口中的run()方法 *  3)在主线程中创建该类的实例对象, *  4)创建Thread类对象,将3)创建的这个对象作为参数进行传递 *  5)分别启动线程 * @author 小鑫 * */public class ThreadDemo {    public static void main(String[] args) {        //创建MyRunnable实例对象        MyRunnable my= new MyRunnable();        //创建线程对象        //public Thread(Runnable target)        //Thread t1 = new Thread(my);        //Thread t2 = new Thread(my);        //public Thread(Runnable target,String name)        Thread t1 = new Thread(my, "线程1");        Thread t2 = new Thread(my, "线程2");        t1.start();        t2.start();    }}class MyRunnable implements Runnable{    @Override    public void run() {        for(int x=0;x<100;x++){            //getName()是Thread类中的方法,间接使用Thread类的静态功能获得线程名称            System.out.println(Thread.currentThread().getName()+":"+x);        }    }}

2、检验多线程安全问题的标准(以后在判断一个多线程序是否有安全问题的标准)
* 1)当前是否是一个多线程环境
* 2)多线程环境中是否有共享数据
* 3)是否有多条语句对共享数据进行操作

package org.westos_07_模拟多线程_电影院卖票案例;/** * 为了模拟电影院卖票更真实的场景,每一个窗口卖票应该延迟操作 *  在接口自实现类中,在run()方法中让每一个线程执行睡眠0.1秒 *  *加入延迟操作: *      1)一张票可能被卖多次 *              100张票会出现多次 *          CPU的执行具有原子性操作 *      2)可能出现负票 *          1,0,-1 *      延迟操作和线程随机性导致 * * *这两种情况都属于线程安全问题,现在写的这个代码是一种有问题的代码? *  如何解决多线程的安全问题呢? *  检验多线程安全问题的标准(以后在判断一个多线程序是否有安全问题的标准) *      1)当前是否是一个多线程环境 *      2)多线程环境中是否有共享数据 *      3)是否有多条语句对共享数据进行操作 * *就目前这个电影院卖票这个案例, *      1)是多线程环境,因为要实现3个窗口同时卖票 *      2)有共享数据,比如:tickets *      3)有多条语句对当前这个共享数据进行操作 *       *优化改进: *  1)多线程环境和共享数据改变不了,突破口就是3)条件:将多条语句对共享数据的操作进行更改 *   *      将多条语句对共享数据进行操作的代码用代码块包起来 *      使用同步代码块:synchronized(同步锁对象){ *              多条语句对共享数据的操作; *      } * @author 小鑫 */public class SellTicketDemo {    public static void main(String[] args) {        //创建线程实例对象        TicketThread tt1 = new TicketThread();        TicketThread tt2 = new TicketThread();        TicketThread tt3 = new TicketThread();        //设置名称        tt1.setName("窗口1");        tt2.setName("窗口2");        tt3.setName("窗口3");        //启动线程        tt1.start();        tt2.start();        tt3.start();    }}class TicketThread extends Thread{    //private int tickets=100;    //定义100张票,票被三个线程公用,用static修饰    private static int tickets=100;    @Override    public void run() {        while(true){            try {                    Thread.sleep(100);                } catch (InterruptedException e) {                    e.printStackTrace();                }            if(tickets>0){                              System.out.println(getName()+"正在出售第"+(tickets--)+"张票");            }        }    }}

3、多线程同步机制

package org.westos_08_线程同步机制_电影院卖票案例;/** * 就目前这个电影院卖票这个案例, 1)是多线程环境,因为要实现3个窗口同时卖票 2)有共享数据,比如:tickets * 3)有多条语句对当前这个共享数据进行操作 *  * 优化改进: 1)多线程环境和共享数据改变不了,突破口就是3)条件:将多条语句对共享数据的操作进行更改 *  * 将多条语句对共享数据进行操作的代码用代码块包起来 Java的同步机制: 使用同步代码块:synchronized(同步锁对象){ * 多条语句对共享数据的操作; } *  * 同步锁对象:应该每一个线程都要使用这个锁对象(同步锁):理解为门的开和关 使用同步代码块可以解决线程安全问题 *  * @author 小鑫 *  */public class SellTicketDemo {    public static void main(String[] args) {        // 创建TicketThread对象        TicketThread tt = new TicketThread();        // 创建线程对象        Thread t1 = new Thread(tt, "窗口1");        Thread t2 = new Thread(tt, "窗口2");        Thread t3 = new Thread(tt, "窗口3");        // 启动线程        t1.start();        t2.start();        t3.start();    }}class TicketThread implements Runnable {    // 定义100张票    private static int tickets = 100;    // 设置锁对象,三个线程必须使用同一个锁对象    // 可以是Object类型,任意的Java类    private Object obj = new Object();    @Override    public void run() {        // 一直邮有票        while (true) {            // 睡眠0.1秒            synchronized (obj) {                if (tickets > 0) {                    try {                        Thread.sleep(100);                    } catch (InterruptedException e) {                        // TODO Auto-generated catch block                        e.printStackTrace();                    }                    System.out.println(Thread.currentThread().getName()                            + "正在出售第" + (tickets--) + "张票");                }            }        }    }}

4、同步方法

package org.westos_09_线程同步机制_同步方法_电影院卖票案例;/** * 同步方法 * @author 小鑫 */public class SellTeckesDemo {    public static void main(String[] args) {        // 创建TecketThread对象        TecketThread tt = new TecketThread();        // 创建线程实例对象        Thread t1 = new Thread(tt, "窗口1");        Thread t2 = new Thread(tt, "窗口2");        Thread t3 = new Thread(tt, "窗口3");        // 启动线程        t1.start();        t2.start();        t3.start();    }}class TecketThread implements Runnable {    // 定义100张被共用的票,不能修改    private static int tickets = 100;    // 创建锁对象    private Object obj = new Object();    private int x;    @Override    public void run() {        while (true) {            if (x % 2 == 0) {                //静态时的同步锁对象--->类名.class                //静态同步方法:要通过反射获取Class类对象(当前类的字节码文件对象)                synchronized (TecketThread.class) {                    if (tickets > 0) {                        try {                            //睡眠0.1秒                            Thread.sleep(100);                        } catch (InterruptedException e) {                            e.printStackTrace();                        }                        System.out.println(Thread.currentThread().getName()                                + "正在出售第" + (tickets--) + "张票");                    }                }            } else {                //sellTicket();            }        }    }    // 非静态同步方法,锁对象是this    /*private synchronized void sellTicket() {        if (tickets > 0) {            // 设置线程睡眠0.1秒            try {                Thread.sleep(100);            } catch (InterruptedException e) {                e.printStackTrace();            }            System.out.println(Thread.currentThread().getName() + "正在出售第"                    + (tickets--) + "张票");        }    }*/    //静态同步方法,锁对象是(类名.class)    private static synchronized void sellTicket() {        if (tickets > 0) {            // 设置线程睡眠0.1秒            try {                Thread.sleep(100);            } catch (InterruptedException e) {                e.printStackTrace();            }            System.out.println(Thread.currentThread().getName() + "正在出售第"                    + (tickets--) + "张票");        }    }}

day21

一、同步锁

1、Lock锁
* Jdk5以后Java提供了一个更具体的锁对象:Lock Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作
* Lock是一个接口,所以它在使用的是 ReentrantLock子实现类
* public void lock()获取锁。

package org.westos_01_Lock锁;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;/** * public void lock()获取锁。  * public void unlock()试图释放此锁 *  * @author 小鑫 */public class SellTicketDemo {    public static void main(String[] args) {        // 创建TicketThread对象        TicketThread tt = new TicketThread();        // 创建线程实例对象        Thread t1 = new Thread(tt, "窗口1");        Thread t2 = new Thread(tt, "窗口2");        Thread t3 = new Thread(tt, "窗口3");        // 启动线程        t1.start();        t2.start();        t3.start();    }}class TicketThread implements Runnable {    // 定义100张票    private static int tickets = 100;    // 锁对象    private Object obj = new Object();    // 定义一个具体锁对象    private Lock l = new ReentrantLock();    @Override    public void run() {        // oldMethod();        // 一直有票        while (true) {            // 获取锁            try {                l.lock();                if (tickets > 0) {                    // 睡眠0.1秒                    try {                        Thread.sleep(100);                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                    System.out.println(Thread.currentThread().getName() + "正在出售第"                            + (tickets--) + "张票");                }            } finally{                //释放锁对象                l.unlock();            }        }    }    private void oldMethod() {        // 一直有票        while (true) {            synchronized (obj) {                if (tickets > 0) {                    // 睡眠0.1秒                    try {                        Thread.sleep(100);                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                    System.out.println(Thread.currentThread().getName()                            + "正在出售第" + (tickets--) + "张票");                }            }        }    }}

2、死锁现象
* 死锁线程:两个或者两个以上的线程出现了互相等待的情况,就会出现死锁!

package org.westos_02_死锁;/** * 使用同步机制可以解决多线程的安全问题,但是自身也会有弊端: *  1)同步---->执行效率低(每一个线程在抢占到CPU的执行权,会去将(门)关闭,别的线程进不来) *  2)容易出现死锁现象 * @author 小鑫 */public class DieLockDemo {    public static void main(String[] args) {        //创建线程对象        DieLock dl1 = new DieLock(true);        DieLock dl2 = new DieLock(false);        //启动线程        dl1.start();        dl2.start();    }}class MyLock{    //创建两把锁对象    public static final Object objA = new Object();    public static final Object objB = new Object();}class DieLock extends Thread{    //定义一个成员变量    private boolean flag;    public DieLock(boolean flag){        this.flag=flag;    }    @Override    public void run() {        if(flag){            synchronized(MyLock.objA){                System.out.println("if objA");                synchronized (MyLock.objB) {                    System.out.println("if objB");                }            }        }else{            synchronized(MyLock.objB){                System.out.println("else objB");                synchronized(MyLock.objA){                    System.out.println("else objA");                }            }        }    }}

3、生产者消费者模式

package org.westos_03_生产者消费者模式;/** *  * @author 小鑫 */public class StudentDemo {    public static void main(String[] args) {        //创建一个资源对象        Student s=new Student();        //创建生产者消费者资源对象        SetThread st = new SetThread(s);        GetThread gt = new GetThread(s);        //创建线程对象        Thread t1 = new Thread(st);        Thread t2 = new Thread(gt);        //启动线程        t1.start();        t2.start();    }}//资源对象类class Student{    String name;    int age;}//生产者类class SetThread implements Runnable{    private Student s;    public SetThread(Student s){        this.s=s;    }    @Override    public void run() {        //设置资源数据        s.name="张三";        s.age=30;    }}//消费者类class GetThread implements Runnable{    private Student s;    public GetThread(Student s){        this.s=s;    }    @Override    public void run() {        System.out.println(s.name+"---"+s.age);    }}

4、同步机制生产者消费者模式

package org.westos_04_同步生产者消费者模式;/** *  * @author 小鑫 */public class StudentDemo {    public static void main(String[] args) {        //创建资源对象        Student s = new Student();        //创建生产者消费者资源对象        SetThread st = new SetThread(s);        GetThread gt = new GetThread(s);        //创建线程对象        Thread t1 = new Thread(st);        Thread t2 = new Thread(gt);        //启动线程        t1.start();        t2.start();    }}// 学生资源对象类class Student {    String name;    int age;}// 生产者线程class SetThread implements Runnable {    private Student s;    public SetThread(Student s) {        this.s = s;    }    private int x;    @Override    public void run() {        // 同步机制        while (true) {            synchronized (s) {                if (x % 2 == 0) {                    s.name = "张三";                    s.age = 30;                } else {                    s.name = "李四";                    s.age = 40;                }                x++;            }        }    }}//消费者线程class GetThread implements Runnable{    private Student s;    public GetThread(Student s){        this.s=s;    }    @Override    public void run() {        while(true){            synchronized (s) {                System.out.println(s.name + "---" + s.age);            }        }    }}

5、同步机制等待唤醒机制生产者消费者模式

package org.westos_05_同步机制_等待唤醒机制_生产者消费者模式;/** *  * @author 小鑫 */public class StudentDemo {    public static void main(String[] args) {        //创建资源对象        Student s = new Student();        //创建生产者消费者资源对象        SetThread st = new SetThread(s);        GetThread gt = new GetThread(s);        //创建线程对象        Thread t1 = new Thread(st);        Thread t2 = new Thread(gt);        //启动线程        t1.start();        t2.start();    }}//资源对象学生类class Student{    String name;    int age;    //声明标记    boolean flag;//默认没有数据,如果true,则说明有数据}//生产者线程class SetThread implements Runnable{    private Student s;    public SetThread(Student s){        this.s=s;    }    private int x;    @Override    public void run() {        while(true){            //同步机制            synchronized(s){                //判断是否有数据                /**                 * 如果生产者先抢到CPU执行权,判断是否有数据                 * 如果没有数据,则释放锁对象,生产数据;                 * 如果有数据了,修改标记,通知消费者消费数据,唤醒等待状态                 */                if(s.flag){                    //等待                    try {                        s.wait();//阻塞式方法,立即释放锁                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }                if(x%2==0){                    s.name="张三";                    s.age=30;                }else{                    s.name="李四";                    s.age=40;                }                x++;                //修改标记                s.flag=true;                //有数据了,通知t2消费者线程来消费数据                //唤醒等待这种状态                s.notify();            }        }    }   }//消费者线程class GetThread implements Runnable{    private Student s;    public GetThread(Student s){        this.s=s;    }    @Override    public void run() {        while(true){            synchronized(s){                //判断是否有数据                               /**                 * 消费者先抢到CPU执行权,判断是否有数据,如果有数据则输出;                 * 如果没有数据,立即释放锁对象,并修改标记,通知生产者生产数据,唤醒等待状态                 */                if(!s.flag){                    try {                        s.wait();//调用时立即释放锁                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }                System.out.println(s.name+"---"+s.age);                //修改标记                s.flag=false;                //通知t1生产者线程,没有数据了,该生产数据了                //唤醒t1线程                s.notify();            }        }    }}

6、最终版生产者消费者模式

package org.westos_06_最终版_生产者消费者模式;/** * 最终版代码: *      现在将资源对象Student中的成员变量私有化 *      并且给当前类中提供两个方法,同步方法 *      在两个线程:生产者线程和消费者中线程,注意调用这两个方法就可以了! * @author 小鑫 * */public class StudentDemo {    public static void main(String[] args) {        //创建资源对象        Student s = new Student();        //创建生产消费资源对象        SetThread st = new SetThread(s);        GetThread gt = new GetThread(s);        //创建线程对象        Thread t1 = new Thread(st);        Thread t2 = new Thread(gt);        //启动线程        t1.start();        t2.start();    }}class Student{    private String name;    private int age;    //声明一个变量    private boolean flag;    //默认没有数据    //set(String name,int age)方法,产生数据数据    public synchronized void set(String name, int age){        //判断是否有数据        if(this.flag){            //没有数据,等待状态            try {                this.wait();            } catch (InterruptedException e) {                e.printStackTrace();            }        }        //产生数据        this.name=name;        this.age=age;        //修改标记        this.flag=true;        //有数据了,通知消费者线程        this.notify();//唤醒等待这种状态    }    public  synchronized void get(){        if(!this.flag){            try {                this.wait();            } catch (InterruptedException e) {                e.printStackTrace();            }        }        System.out.println(this.name+"---"+this.age);        //修改标记        this.flag=false;        //通知生产者线程,没有数据,该生产数据        this.notify();//唤醒生产者线程    }}//生产者线程class SetThread implements Runnable{    private Student s;    public SetThread(Student s){        this.s=s;    }    private int x;    @Override    public void run() {        while(true){            if(x%2==0){                s.set("张三", 30);            }else{                s.set("李四", 40);            }            x++;        }    }}//消费者线程class GetThread implements Runnable{    private Student s;    public GetThread(Student s){        this.s=s;    }    @Override    public void run() {        while(true){            s.get();        }    }}

二、线程组

  • 线程组表示一个线程的集合:Java允许一个线程中有多个线程
package org.westos_07_线程组;/** * 线程组表示一个线程的集合:Java允许一个线程中有多个线程 * @author 小鑫 */public class ThreadGroupDemo {    public static void main(String[] args) {        //获取线程组名称        //method1();        //设置线程组名称        method2();    }    //设置线程组名称    private static void method2() {        //public ThreadGroup(String name)构造一个新线程组        ThreadGroup tg = new ThreadGroup("新线程");        //创建资源对象        MyRunnable my = new MyRunnable();        //public Thread(ThreadGroup group,Runnable target ,String name){}        //创建线程类对象,并且将线程组对象作为参数进行传递        Thread t1 = new Thread(tg, my, "线程1");        Thread t2 = new Thread(tg, my, "线程2");        ThreadGroup tg1 = t1.getThreadGroup();        ThreadGroup tg2 = t2.getThreadGroup();        System.out.println(tg1.getName());        System.out.println(tg2.getName());    }    //获取线程组名称    private static void method1() {        //创建资源对象        MyRunnable my = new MyRunnable();        //创建线程对象        Thread t1 = new Thread(my);        Thread t2 = new Thread(my);        //启动线程        //t1.start();        //t2.start();        //获取线程组对象        //public final ThreadGroup getThreadGroup()返回该线程所属的线程组        ThreadGroup tg1 = t1.getThreadGroup();        ThreadGroup tg2 = t2.getThreadGroup();        //获取线程组名称        String name1 = tg1.getName();        String name2 = tg2.getName();        //子线程默认线程组名称:main        System.out.println(name1);//main        System.out.println(name2);//main        //所以线程默认线程组名称是main        System.out.println(Thread.currentThread().getThreadGroup().getName());    }}class MyRunnable implements Runnable {    @Override    public void run() {        for (int x = 0; x < 100; x++) {            System.out.println(Thread.currentThread().getName() + ":" + x);        }    }}

三、多线程实现的第三种方式

1、Executors工厂类产生线程池

package org.westos_08_线程池;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;/** * 多线程程序的实现方式3: * Executors工厂类来产生线程池 public static ExecutorServicenewFixedThreadPool(int nThreads) Executors工厂类中的这个方法参数直接指定在当前线程池中有多少个线程 * 方法的返回值是ExecutorService对象,该对象表示一个线程池 ExecutorsService : * 接口中的方法 Future<?>submit(Runnable task) <T> Future<T> submit(Callable<T> task) * @author 小鑫 */public class ExecutorsDemo {    public static void main(String[] args) {        //创建线程对象,使用Executors工厂类        //public static ExecutorService newFixedThreadPool(int nThreads)        ExecutorService pool = Executors.newFixedThreadPool(2);        //使用ExecutorsService(跟着多个异步任务)方法        //submit(Runnable task)        pool.submit(new MyRunnable());        pool.submit(new MyRunnable());        //结束线程池        pool.shutdown();        //pool-1-thread-1:x        //pool-1-thread-2:x    }}class MyRunnable implements Runnable {    @Override    public void run() {        for (int x = 0; x < 100; x++) {            System.out.println(Thread.currentThread().getName() + ":" + x);        }    }}

2、Callable接口

package org.westos_08_线程池;import java.util.concurrent.Callable;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;/** * ExecutorsService :接口中的方法 * <T> Future<T> submit(Callable<T> task) * 该返回值表示:异步计算的结果! * @author 小鑫 */public class CallableDemo {    public static void main(String[] args) {        //创建线程对象,工厂类        ExecutorService Threadpool = Executors.newFixedThreadPool(2);        //提交Callable任务(异步任务)        Threadpool.submit(new MyCallable());        Threadpool.submit(new MyCallable());        //结束线程        Threadpool.shutdown();        //pool-1-thread-1:x        //pool-1-thread-2:x    }}class MyCallable implements Callable<Object>{    @Override    public Object call() throws Exception {        for(int x=0;x<100;x++){            System.out.println(Thread.currentThread().getName()+":"+x);        }        return null;    }}

3、Callable接口求和

package org.westos_09_线程池Callable求和;import java.util.concurrent.Callable;import java.util.concurrent.ExecutionException;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Future;public class CallableDemo2 {    public static void main(String[] args) throws InterruptedException, ExecutionException {        //创建线程对象,工厂类        ExecutorService Threadpool = Executors.newFixedThreadPool(2);        //提交两个异步任务,计算1-100,1-200的和        Future<Integer> f1 = Threadpool.submit(new MyCallable(100));        Future<Integer> f2 = Threadpool.submit(new MyCallable(200));        //分别调用Future接口中  get()方法,返回具体的结果        Integer i1 = f1.get();        Integer i2 = f2.get();        System.out.println("1-100的和是:"+i1);        System.out.println("1-200的和是:"+i2);        //1-100的和是:5050        //1-200的和是:20100    }}class MyCallable implements Callable<Integer>{    private int number;    public MyCallable(int number){        this.number=number;    }    @Override    public Integer call() throws Exception {        int sum=0;        for(int x=1;x<=number;x++){            sum += x;        }        return sum;         }}

4、多线程匿名内部类
多线程中匿名内部类的方式
* new 类名(具体类,抽象类),接口{
* 重写/实现方法;
* }
匿名内部类本质:
* 继承该类或者实现该接口的子类对象

package org.westos_09_线程池Callable求和;/** * 多线程中匿名内部类的方式 *    new 类名(具体类,抽象类),接口{ *        重写/实现方法; *    } * 匿名内部类本质: *       继承该类或者实现该接口的子类对象 * @author 小鑫 */public class ThreadDemo {    public static void main(String[] args) {        //继承Thread类        new Thread(){            @Override            public void run(){                for(int x=0;x<100;x++){                    System.out.println(getName()+":"+x);                }            }        }.start();        //Runnable接口        new Thread(new Runnable(){            @Override            public void run(){                for(int x = 0 ; x < 100 ; x ++){                    System.out.println(Thread.currentThread().getName()+":"+x);                }            }        }).start();        new Thread(new Runnable(){            @Override            public void run() {                for(int x = 0 ; x <100 ; x ++){                    System.out.println("hello"+x);                }                   }               }){            @Override            public void run() {                for(int x = 0 ; x <100 ; x ++){                    System.out.println("world"+x);                }            }        }.start();    }}

四、定时器Timer

定时器:Timer
* public void schedule(TimerTask task,Date time)安排在指定的时间执行指定的任务
* public void schedule(TimerTask task, long delay)在多少毫秒后执行指定任务
* public void schedule(TimerTask task, long delay, long period)在多少毫秒后,执行任务,并且每个多少毫秒重复执行
* public void cancel()终止此计时器,丢弃所有当前已安排的任务

1、 public void schedule(TimerTask task, long delay)在多少毫秒后执行指定任务

package org.westos_10_定时器Timer;import java.util.Timer;import java.util.TimerTask;/** * 需求:3秒后执行爆炸任务 * @author 小鑫 */public class TimerDemo {    public static void main(String[] args) {        //创建计时器        Timer t = new Timer();        //public void schedule(TimerTask task, long delay)在多少毫秒后执行指定任务        t.schedule(new MyTask(t), 3000);    }}class MyTask extends TimerTask{    private Timer t;    public MyTask(){    }    public MyTask(Timer t){        this.t=t;    }    @Override    public void run() {        System.out.println("boom...");        t.cancel();//取消任务    }}

2、安排在指定的时间执行指定的任务

package org.westos_10_定时器Timer;import java.util.Timer;import java.util.TimerTask;/** * public void schedule(TimerTask task, long delay, long period) * 在多少毫秒后,执行任务,并且每个多少毫秒重复执行 *  * 需求:3秒后执行爆炸任务,每隔2秒重复爆炸 * @author 小鑫 */public class TimerDemo2 {    public static void main(String[] args) {        //创建计时器        Timer t = new Timer();        t.schedule(new MyTask2(), 3000, 2000);    }}class MyTask2 extends TimerTask{    @Override    public void run() {        System.out.println("boom...");    }}

3、在指定的时间删除我们的指定目录

package org.westos_10_定时器Timer;import java.io.File;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Timer;import java.util.TimerTask;/** * 需求:在指定的时间删除我们的指定目录 * @author 小鑫 */public class TimerTest {    public static void main(String[] args) throws ParseException {        //创建定时器        Timer t = new Timer();        //指定删除日期        String s="2017-12-8 10:40:00";        //创建SimpleDateFormat对象        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");        Date date = sdf.parse(s);        //public void schedule(TimerTask task,Date time)安排在指定的时间执行指定的任务        t.schedule(new DeleteFolder(), date);    }}class DeleteFolder extends TimerTask{    @Override    public void run() {        File srcFolder = new File("demo");        deleteFolder(srcFolder);    }    private void deleteFolder(File srcFolder) {        //获取srcFolder文件及文件夹数组        File[] fileArray = srcFolder.listFiles();        //非空判断        if(fileArray!=null){            for(File file:fileArray){                //判断是否是文件夹                if(file.isDirectory()){                    //递归删除,回到该方法                    deleteFolder(file);                }else{                    //不是文件夹,直接删除                    System.out.println(file.getName()+"---"+file.delete());                }            }            System.out.println(srcFolder.getName()+"---"+srcFolder.delete());        }    }}

五、IO流存入文件注册登录案例

用户实体类

package org.westos_11_User;/** * 用户实体 * @author 小鑫 * */public class User {    private String username;    private String password;    public User(){    }    public String getUsername() {        return username;    }    public void setUsername(String username) {        this.username = username;    }    public String getPassword() {        return password;    }    public void setPassword(String password) {        this.password = password;    }}

注册登录接口

package org.westos_11_User;public interface UserDao {    /**     * 用户登录功能     *      * @param username     *        登录输入的用户名     * @param password     *        登录输入的密码     * @return      *        返回是否登录成功     */    public abstract boolean isLogin(String username, String password);    /**     * 用户注册功能     * @param user     */    public abstract void regist(User user);}

用户操作接口实现类

package org.westos_11_User;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.File;import java.io.FileNotFoundException;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;/** * 用户操作接口实现类 * @author 小鑫 * */public class UserDaoImpl implements UserDao {    //File对象封装文件    private static  File file=new File("user.txt");    static{        try {            file.createNewFile();        } catch (IOException e) {            System.out.println("文件创建失败");        }    }    //登录功能    @Override    public boolean isLogin(String username, String password) {        //定义标记        boolean flag=false;        //创建字符输入流        BufferedReader br=null;        try {            br=new BufferedReader(new FileReader(file));            //一次读一行            String line=null;            while((line=br.readLine())!=null){                String[] s = line.split("=");                if(s[0].equals(username) && s[1].equals(password)){                    //登录成功,修改标记                    flag=true;                }            }        } catch (FileNotFoundException e) {            System.out.println("登录时找不到文件导致失败");        } catch (IOException e) {            System.out.println("用户登录失败");        }finally{            //释放资源            if(br!=null){                try {                    br.close();                } catch (IOException e) {                    System.out.println("释放资源失败");                }            }        }        return flag;    }    //注册功能    @Override    public void regist(User user) {        //注册使用字符缓冲输出流        BufferedWriter bw=null;        try {            bw=new BufferedWriter(new FileWriter(file ,true));            //固定一种格式            bw.write(user.getUsername()+"="+user.getPassword());            bw.flush();            bw.newLine();        } catch (IOException e) {            System.out.println("用户注册失败");        }finally{            //针对流对象非空判断            if(bw!=null){                try {                    bw.close();                } catch (IOException e) {                    System.out.println("用户注册释放资源失败");                }            }        }    }}

用户测试类

package org.westos_11_User;import java.util.Scanner;/** * 用户测试类 * @author 小鑫 * */public class UserTest {    public static void main(String[] args) {        while(true){            //选择界面            System.out.println("--------欢迎光临--------");            System.out.println("1 注册");            System.out.println("2 登录");            System.out.println("3 退出");            //创建键盘录入对象            Scanner sc = new Scanner(System.in);            //调用功能            UserDaoImpl ud = new UserDaoImpl();            System.out.println("请选择");            String choice = sc.nextLine();            switch(choice){            case "1":                //注册界面                System.out.println("------注册界面------");                System.out.println("请输入用户名");                String newUsername = sc.nextLine();                System.out.println("请输入密码");                String newPassword = sc.nextLine();                //创建用户对象,封装用户名和密码                User u = new User();                u.setUsername(newUsername);                u.setPassword(newPassword);                //调用东功能                ud.regist(u);                System.out.println("恭喜您,注册成功");                break;            case "2":                //登陆界面                System.out.println("------登陆界面------");                System.out.println("请输入用户名:");                String username = sc.nextLine() ;                System.out.println("请输入密码:");                String password = sc.nextLine() ;                //调用功能                boolean flag = ud.isLogin(username, password);                if(flag){                    System.out.println("登录成功");                    System.exit(0);                         }else{                    System.out.println("登录失败,用户名或密码不正确");                }                break;            case "3":                //退出界面                System.out.println("谢谢使用,欢迎下次光临");                System.exit(0);                break;            }        }    }}
原创粉丝点击