线程

来源:互联网 发布:import java.util. 编辑:程序博客网 时间:2024/06/05 11:04
/** * 创建并启动一个线程的方法 *      1) 实现接口的方式 *          1) 写一个具体类, 实现Runnable接口, 并实现其中的run方法,这个run方法就是线程的入口方法 *          2) 创建这个类的对象, 并以这个对象为实参, 创建Thread类的对象 *          3) 调用Thread对象的start()方法 启动线程 * */
/** * 多线程打印偶数,奇数,体会多线程的交替执行 * 线程的执行,抢占式 */public class ThreadTest {    public static void main(String[] args) {        //利用一个Runnable引用可以创建多个线程,只不过这几个线程共用一个run方法        //但是属于不同的线程,线程创建好的标志,有了栈        //多态        Runnable r = new PrintEven();        Thread t1 = new Thread(r);        t1.setName("子线程1");        t1.start();        Thread t2 = new Thread(r);        t2.setName("子线程2");        t2.start();        Runnable r2 = new PrintOdd();        Thread tt = new Thread(r2);        tt.setName("子线程A");        tt.start();    }}//子线程打印偶数0~100class PrintEven implements Runnable{    private int i ;    @Override    public void run() {        /*         * 该线程要做的事,打印0~100的所有偶数         */        for(i = 0; i < 100; i += 2) {            System.out.println(Thread.currentThread().getName() + ":" + i);        }    }}//子线程打印奇数0~100class PrintOdd implements Runnable{    private int i ;    @Override    public void run() {        /*         * 该线程要做的事情         */        for(i = 1; i < 100; i += 2) {            System.out.println(Thread.currentThread().getName() + ":" + i);        }    }}
/** * 创建线程的第二种方式: *      继承的方式 *      1) 写一个具体类继承自Thread, 重写run方法, 这个run方法是真的入口 *      2) 创建具体类对象, 相当于创建了Thread对象 *      3) 调用Thread对象的.start() */class TestThread extends Thread {    @Override    public void run() {        for (int i = 0; i < 100; i++) {            System.out.println(currentThread().getName() + " : " + i);        }    }}public class ThreadTest {    public static void main(String[] args) {        //自定义子线程        new TestThread().start();        //main线程        for (int i = 0; i < 100; i++) {            System.out.println(Thread.currentThread().getName() + ":" + i);        }    }}
/** * 1.在main方法中创建并启动一个线程,线程循环随机打印100以内的整数,直到主线程从键盘读取了"Q"命令 *  */import java.util.Scanner;public class GetRandomNumTest {    public static void main(String[] args) {        //创建线程        //利用实现Runnable接口创建线程本质还是创建Thread对象,(利用Runnable引用创建对象)        /*         *     public Thread(Runnable target) {         *          init(null, target, "Thread-" + nextThreadNum(), 0);         *     }         */        //多态        Runnable r = new GetRandomNum();        Thread t = new Thread(r);        //开启线程        t.start();        //创建输入流从键盘获取信息        Scanner sc = null;        try {            sc = new Scanner(System.in);            while(sc.hasNext()) {                String str = sc.nextLine();                //不区分大小写                if(str.equalsIgnoreCase("Q")) {                    ((GetRandomNum)r).setStopflag(true);                    break;                }            }        } catch (Exception e) {            e.printStackTrace();        } finally {            //对于Scanner对象关流不需要处理异常            sc.close();        }    }}/* * 线程循环随机打印100以内的整数,直到主线程从键盘读取"Q" */class GetRandomNum implements Runnable {    private boolean stopflag = false;    public boolean isStopflag() {        return stopflag;    }    public void setStopflag(boolean stopflag) {        this.stopflag = stopflag;    }    @Override    public void run() {        /*         * 因为线程要循环随机打印100以内的整数,直到主线程从键盘获取"Q"         * 因此并不知道线程体中要循环多少次,要设置无限循环         * 同时因为要从外界来终止循环,所以要设置一个控制循环的布尔变量,当外界条件满足是修改布尔变量值,使得循环终止         */        while(!stopflag) {            //打印当前线程名字和生成的随机整数            System.out.println(Thread.currentThread().getName() + ":" + (int)(Math.random() * 100));        }    }}
import java.io.BufferedReader;import java.io.InputStreamReader;/** * 2.在main方法中启动两个线程。第一个线程循环随机打印100以内的整数,直到第二个线程从键盘读取了"Q"命令 * 将线程将要执行的任务放在线程体中 */public class GetRandomNumTest2 {    public static void main(String[] args) {        Runnable r = new GetRandomNumber();        Thread t = new Thread(r);        Runnable r1 = new KeyListener((GetRandomNumber)r);        Thread t1 = new Thread(r1);        t.start();        t1.start();    }}class GetRandomNumber implements Runnable {    private boolean stopflag = false;    public boolean isStopflag() {        return stopflag;    }    public void setStopflag(boolean stopflag) {        this.stopflag = stopflag;    }    @Override    public void run() {        while(!stopflag) {            int randomNum = (int)(Math.random() * 100);            System.out.println(Thread.currentThread().getName() + "  " + randomNum);        }    }}/* * 再设置一个线程控制循环结束,通过不断的监听键盘数据,进行判断,然后对循环进行控制 */class KeyListener implements Runnable {    private GetRandomNumber getRandomNumber;    public KeyListener(GetRandomNumber getRandomNumber) {        this.getRandomNumber = getRandomNumber;    }    @Override    public void run() {        //设置输入流,从键盘获取信息,然后判断,对循环进行控制        InputStreamReader isr = null;        BufferedReader bfr = null;        try {            isr = new InputStreamReader(System.in);            bfr = new BufferedReader(isr);            //方法2            String string = bfr.readLine();            while(true) {                if(string.equalsIgnoreCase("Q")) {                    getRandomNumber.setStopflag(true);                    break;                }                string = bfr.readLine();            }            /*方法1            //从键盘获取信息            String string = bfr.readLine();            //若不是q继续获取            while(!string.equalsIgnoreCase("Q")) {                string = bfr.readLine();            }            getRandomNumber.setStopflag(true);            */        } catch (Exception e) {            e.printStackTrace();        } finally {            try {                bfr.close();            } catch (Exception e2) {                e2.printStackTrace();            }        }    }}
import java.util.ArrayList;import java.util.List;/** * 1.编写程序,在main中创建一个线程。线程每隔一定时间(200ms以内的随机时间)产生一个0~100之间的随机整数 * 打印后将该整数放到集合中,共产生100个整数,全部产生后,睡眠30秒,然后将集合内容打印输出 * 在main线程中,唤醒上述睡眠的线程,使其尽快打印集合内容 *  * 首先要先构建目标线程类,在线程体中实现线程需要做的事情。 * 然后利用main线程唤醒 *实现精准控制,boolean变量 */public class GetDataTest {    public static void main(String[] args) {        //创建获取整数的线程        Runnable r = new GetData();        Thread t = new Thread(r);        t.start();        /*        //在main中实现精准控制打断        while(!((GetData)r).isFlag()) {            try {                Thread.sleep(10);            } catch (InterruptedException e) {                e.printStackTrace();            }        }        //当flag为true时,while循环结束执行下面语句,下面这个语句打断睡觉        t.interrupt();        */        //利用另一个线程做打断的工作        Runnable r1 = new Keylisten((GetData)r, t);        Thread t1 = new Thread(r1);        t1.start();    }}/* * 线程的任务,将这些任务写在线程的run方法中就行 * 线程每隔一定时间(200ms以内的随机时间)产生一个0~100之间的随机整数 * 打印后将该整数放到集合中,共产生100个整数,全部产生后,睡眠30秒,然后将集合内容打印输出 */class GetData implements Runnable {    //因为需要从外界将线程唤醒,需要设置一个标记    private boolean flag = false;    public boolean isFlag() {        return flag;    }    public void setFlag(boolean flag) {        this.flag = flag;    }    @Override    public void run() {        /*         * 该类线程完成的任务         */        //创建一个list集合保存生成的随机数        List<Integer> list = new ArrayList<Integer>();        //需要生成100个随机数        for(int i = 0; i < 100; i++) {            //获取随机整数            int randomNum = (int)(Math.random() * 100);            //打印随机整数            System.out.println(randomNum);            //保存到集合中            list.add(randomNum);            //睡觉            try {                //获取随机的睡觉时间                long randomTime = (int)(Math.random() * 200);                //睡觉                Thread.sleep(randomTime);            } catch (InterruptedException e) {                //处理睡觉被打断异常                System.out.println("小睡被打断");            }        }        //当数据生成完成后,将flag修改,便于外界唤醒线程        flag = true;        //全部完成后,睡一大觉        try {            Thread.sleep(30 * 1000);        } catch (InterruptedException e) {            System.out.println("长睡被打断");        }        //遍历打印集合        for (Integer integer : list) {            System.out.print(integer + " ");        }    }}class Keylisten implements Runnable {    //对于对象关联,先写方法,需要什么,就关联什么    //关联两个类    private GetData r;    private Thread t;    public Keylisten(GetData r, Thread t) {        this.r = r;        this.t = t;    }    @Override    public void run() {        /*         * 这个线程要精准的唤醒获取数据的线程         */        while(!((GetData)r).isFlag()) {            try {                Thread.sleep(10);            } catch (InterruptedException e) {                e.printStackTrace();            }        }        t.interrupt();    }}
/** * 银行有一个账户Account包含属性name, balance * 有两个柜台分别同时向同一个账户存3000元,每次存1000,存3次。每次存完打印账户余额。睡眠10毫秒 *  * 问题:该程序是否有安全问题,如果有,如何解决? *  * 扩展练习 : 一个柜台Deposit存3000元, 每次存1000,存3次 另一个柜台Withdraw取3000元, 每次取1000,取3次 *//* * 一个柜台就是一个线程,将账户与存取钱操作分开 */public class Account {    private String name;    private int balance;    public Account() {    }    public Account(String name, int balance) {        super();        this.name = name;        this.balance = balance;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public int getBalance() {        return balance;    }    public void setBalance(int balance) {        this.balance = balance;    }    @Override    public String toString() {        return "Account [name=" + name + ", balance=" + balance + "]";    }}
/* * 扩展练习 : 一个柜台Deposit存3000元, 每次存1000,存3次 另一个柜台Withdraw取3000元, 每次取1000,取3次 * 有两个柜台分别同时向同一个账户存3000元,每次存1000,存3次。每次存完打印账户余额。睡眠10毫秒 * 每一个柜台相当于一个线程,对于存款,取款操作不同,因此需要不同的线程类 */public class Deposit implements Runnable{    private Account account;    public Deposit(Account account) {        this.account = account;    }    @Override    public void run() {        synchronized ("") {            for(int i = 0; i < 3; i++) {                account.setBalance((account.getBalance() + 1000));                System.out.println(Thread.currentThread().getName() + "  " + "账户余额:" + account.getBalance());                try {                    Thread.sleep(10);                } catch (InterruptedException e) {                    System.out.println("在睡觉时被打断。");                }            }        }    }}
/* * 取钱柜台也相当于一个线程 * 另一个柜台Withdraw取3000元, 每次取1000,取3次 * 利用使用相同的同步锁将取钱和存钱同步 */public class Withdraw implements Runnable{    private Account account;    public Withdraw(Account account) {        this.account = account;    }    @Override    public void run() {        synchronized ("") {            for(int i = 0; i < 3; i++) {                account.setBalance(account.getBalance() - 1000);                System.out.println(Thread.currentThread().getName() + "  " + "账户余额:" + account.getBalance());                try {                    Thread.sleep(10);                } catch (InterruptedException e) {                    System.out.println("在休息时被打断");                }            }        }    }}
/** * 测试类 * */public class AccountTest {    public static void main(String[] args) {        Account account = new Account("张三", 5000);        Runnable rdeposit = new Deposit(account);        Thread td1 = new Thread(rdeposit);        td1.setName("存钱柜台A");        td1.start();        Thread td2 = new Thread(rdeposit);        td2.setName("存钱柜台B");        td2.start();        Runnable rwithdraw = new Withdraw(account);        Thread tw1 = new Thread(rwithdraw);        tw1.setName("取钱柜台1");        tw1.start();    }}
2 0