线程

来源:互联网 发布:恩典壁纸软件 编辑:程序博客网 时间:2024/06/03 20:38

一、进程
1、运行时(Runtime)应用程序
2、进程之间的内存不是共享的(独占)
3、进程间通信使用的是socket(套接字)

=======================
二、多线程
1、进程内并发执行的代码段,关键就是并发
2、线程之间共享内存
3、创建灵活响应的桌面程序(QQ、迅雷)
4、每个运行着的线程对应一个栈stack
5、应用程序至少有一个线程(主线程)

====================

Java中使用线程继承java.lang.Thread
测试代码1:

public class ThreadDemo1{    public static void main(String[] arg){        MyThread t1 = new MyThread();        YourThread t2 = new YourThread();        t1.start();        t2.start();    }}class MyThread extends Thread{    public void run(){        for(;;){            System.out.println("hello world -1");        }    }}class YourThread extends Thread{    public void run(){        for(;;){            System.out.println("hello world -2");        }    }}

结果:
这里写图片描述

出现的顺序是随机的,但是一旦某个线程抢到资源后将抢占着,比较懒

测试代码2:
Thread.yield()方法:让当前线程让出cpu抢占权,具有谦让之意,瞬时的动作。

public class ThreadDemo2{    public static void main(String[] arg){        MyThread t1 = new MyThread("hello world-1");        MyThread t2 = new MyThread("hello world-2");        t1.start();        t2.start();    }}class MyThread extends Thread{    private String name;    public MyThread(String name){        this.name = name;    }    public void run(){        for(;;){            System.out.println(name);            //yield,放弃,谦让            Thread.yield();        }    }}

结果:
这里写图片描述

线程出现的顺序随机,使用了线程yield方法,放弃一直抢夺资源。

=================================

测试代:3:
Thread.sleep():让当前线程休眠指定毫秒数
释放cpu抢占权,和锁旗标的监控权没有关系

public class ThreadDemo3{    public static void main(String[] arg){        Player p1 = new Player("施瓦辛格",1000);        Player p2 = new Player("成龙",2000);        Player p3 = new Player("李连杰",2500);        Player p4 = new Player("史泰龙",3000);        p1.start();        p2.start();        p3.start();        p4.start();        System.out.println("开局了");    }}class Player extends Thread{    private String name;    private int time;    public Player(String name,int time){        this.name = name;        this.time=time;    }    public void run(){        System.out.println(name+"出发了");        try{            Thread.sleep(time);        }catch(Exception e){            e.getMessage();        }        System.out.println(name+"到了!耗时"+time);    }}

结果:
这里写图片描述

测试代码4:
Thread.join()
当前线程等待指定的线程结束后才能继续进行

public class ThreadDemo3{    public static void main(String[] arg){        Player p1 = new Player("施瓦辛格",1000);        Player p2 = new Player("成龙",2000);        Player p3 = new Player("李连杰",2500);        Player p4 = new Player("史泰龙",3000);        p1.start();        p2.start();        p3.start();        p4.start();        try{            p1.join();            p2.join();            p3.join();            p4.join();        }catch(Exception e){            e.getMessage();        }        System.out.println("开局了");    }}class Player extends Thread{    private String name;    private int time;    public Player(String name,int time){        this.name = name;        this.time=time;    }    public void run(){        System.out.println(name+"出发了");        try{            Thread.sleep(time);        }catch(Exception e){            e.getMessage();        }        System.out.println(name+"到了!耗时"+time);    }}

结果:
这里写图片描述

测试代码5:

public class ThreadDemo3{    public static void main(String[] arg){        Player p4 = new Player("史泰龙",3000);        Player p1 = new Player("施瓦辛格",1000);        Player p3 = new Player("李连杰",2500);        Player p2 = new Player("成龙",2000);        p1.start();        p2.start();        p3.start();        p4.start();        try{            p1.join();            p2.join();            p3.join();            p4.join();        }catch(Exception e){            e.getMessage();        }        System.out.println("开局了");    }}class Player extends Thread{    private String name;    private int time;    public Player(String name,int time){        this.name = name;        this.time=time;    }    public void run(){        System.out.println(name+"出发了");        try{            Thread.sleep(time);        }catch(Exception e){            e.getMessage();        }        System.out.println(name+"到了!耗时"+time);    }}

结果:
这里写图片描述

===============================

daemon:守护,服务员
为其它线程提供服务的线程
若进程中剩余的线程 都是守护线程的话,该线程终止了
Thread.setDaemon(true)

测试代码6:

public class ThreadDemo4{    public static void main(String[] arg){        Box no1 = new Box("no1",3000);        Box no2 = new Box("no2",7000);        Waiter w = new Waiter();        no1.start();        no2.start();        w.start();    }}//线程1class Box extends Thread{    private String no;    private int time;    public Box(String no,int time){        this.no = no;        this.time=time;    }    public void run(){        System.out.println(no+"包房开始消费!");        try{            Thread.sleep(time);        }catch(Exception e){            e.getMessage();        }        System.out.println(no+"包房消费时间:"+time+",结束消费!");    }}//服务员类class Waiter extends Thread{    public void run(){        while(true){            //打印系统当前时间        System.out.println(new java.util.Date());            try{                Thread.sleep(1000);            }catch(Exception e){                e.getMessage();            }        }    }}

结果:
这里写图片描述

测试代码6:

public class ThreadDemo4{    public static void main(String[] arg){        Box no1 = new Box("no1",3000);        Box no2 = new Box("no2",7000);        Waiter w = new Waiter();        //设置线程为守护线程        w.setDaemon(true);        no1.start();        no2.start();        w.start();    }}//线程1class Box extends Thread{    private String no;    private int time;    public Box(String no,int time){        this.no = no;        this.time=time;    }    public void run(){        System.out.println(no+"包房开始消费!");        try{            Thread.sleep(time);        }catch(Exception e){            e.getMessage();        }        System.out.println(no+"包房消费时间:"+time+",结束消费!");    }}//服务员类class Waiter extends Thread{    public void run(){        while(true){            //打印系统当前时间        System.out.println(new java.util.Date());            try{                Thread.sleep(1000);            }catch(Exception e){                e.getMessage();            }        }    }}

结果:
这里写图片描述

=========================

测试代码7:
减减–操作:原子性操作,不会出现重复

public class ThreadDemo5{    public static void main(String[] arg){        Saler s1 = new Saler("s1");        Saler s2 = new Saler("s2");        s1.start();        s2.start();    }}class Saler extends Thread{    private String name;    private static int tickets=100;    public Saler(String name){        this.name=name;    }    public void run(){        while(tickets>0){            System.out.println(name+":"+tickets--);        }    }}

结果:
这里写图片描述

测试代码8:

public class ThreadDemo5{    public static void main(String[] arg){        Saler s1 = new Saler("s1");        Saler s2 = new Saler("s2");        s1.start();        s2.start();    }}class Saler extends Thread{    private String name;    private static int tickets=100;    public Saler(String name){        this.name=name;    }    public void run(){        while(tickets>0){            int temp = tickets;            tickets = tickets-1;            System.out.println(name+":"+temp);        }    }}

结果:
这里写图片描述

测试代码10:

public class ThreadDemo5{    public static void main(String[] arg){        Saler s1 = new Saler("s1");        Saler s2 = new Saler("s2");        s1.start();        s2.start();    }}class Saler extends Thread{    private String name;    private static int tickets=100;    public Saler(String name){        this.name=name;    }    public void run(){        while(tickets>0){            int temp = tickets;            System.out.println(name+":"+temp);            tickets = tickets-1;        }    }}

结果:
这里写图片描述

=======================

线程间通信:共享资源问题
解决办法:加锁,防止并发访问。由并行改为串行。
参照物,锁旗标
测试代码:11:

public class ThreadDemo5{    public static void main(String[] arg){        Saler s1 = new Saler("s1");        Saler s2 = new Saler("s2");        s1.start();        s2.start();    }}class Saler extends Thread{    private String name;    static  Object lock = new Object();    private static int tickets=100;    public Saler(String name){        this.name=name;    }    public void run(){        while(true){            int t=getTickets();            if(t==-1){                return;            }else{                System.out.println(name+":"+t);            }        }    }    public int getTickets(){            synchronized(lock){                int temp = tickets;                tickets = tickets-1;                return temp<1?-1:temp;            }    }}

结果:加了锁旗标,不会出现重复卖票
这里写图片描述

==========================

测试代码12:
锁旗标是非静态成员变量时,就不属于类所有,而是对象所拥有。此时的锁是s1、s2自身对象所拥有的锁,并不是同一把锁。

public class ThreadDemo6{    public static void main(String[] arg){        Saler s1 = new Saler("s1");        Saler s2 = new Saler("s2");        s1.start();        s2.start();    }}class Saler extends Thread{    private String name;    Object lock = new Object();    private static int tickets=100;    public Saler(String name){        this.name=name;    }    public void run(){        while(true){            int t=getTickets();            if(t==-1){                return;            }else{                System.out.println(name+":"+t);            }        }    }    public int getTickets(){            synchronized(lock){                int temp = tickets;                tickets = tickets-1;                return temp<1?-1:temp;            }    }}

结果:
这里写图片描述
并没有看出重复卖票的情况,但是并不代表不会出现重复卖票。
测试代码13:

public class ThreadDemo6{    public static void main(String[] arg){        Saler s1 = new Saler("s1");        Saler s2 = new Saler("s2");        s1.start();        s2.start();    }}class Saler extends Thread{    private String name;    Object lock = new Object();    private static int tickets=100;    public Saler(String name){        this.name=name;    }    public void run(){        while(true){            int t=getTickets();            if(t==-1){                return;            }else{                System.out.println(name+":"+t);            }        }    }    public int getTickets(){            synchronized(lock){                int temp = tickets;                try{                    Thread.sleep(500);                }catch(Exception e){}                tickets = tickets-1;                return temp<1?-1:temp;            }    }}

结果:
这里写图片描述

通过睡眠的方式,可以看到此时的结果就出现了重复卖票。
解决办法:必须用同一把锁旗标,通过创建一个对象,每个线程调用该对象。
测试代码14:

public class ThreadDemo6{    public static void main(String[] arg){        Object lock = new Object();        Saler s1 = new Saler("s1",lock);        Saler s2 = new Saler("s2",lock);        s1.start();        s2.start();    }}class Saler extends Thread{    private String name;    Object lock;    //Object lock = new Object();    private static int tickets=100;    public Saler(String name,Object lock){        this.name=name;        this.lock = lock;    }    public void run(){        while(true){            int t=getTickets();            if(t==-1){                return;            }else{                System.out.println(name+":"+t);            }        }    }    public int getTickets(){            synchronized(lock){                int temp = tickets;                try{                    Thread.sleep(50);                }catch(Exception e){}                tickets = tickets-1;                return temp<1?-1:temp;            }    }}

结果:
这里写图片描述
此时就不会重新重复卖票。

=================
同步代码块:

    synchronized{        ...}

同步代码块执行期间,线程始终持有对象的监控权,其它线程处于阻塞状态。
另一种解决方式:创建卖票池类

测试代码15:

public class ThreadDemo7{    public static void main(String[] arg){        TicketPool pool = new TicketPool();        Saler s1 = new Saler("s1",pool);        Saler s2 = new Saler("s2",pool);        Saler s3 = new Saler("s3",pool);        Saler s4 = new Saler("s4",pool);        s1.start();        s2.start();        s3.start();        s4.start();    }}//售票员class Saler extends Thread{    private String name;    private TicketPool pool;    public Saler(String name,TicketPool pool){        this.name = name;        this.pool = pool;    }    public void run(){        while(true){            int no = pool.getTicket();            if(no==0){                return;            }            else{                System.out.println(name+":"+no);            }        }    }}class TicketPool{    private int tickets = 100;    public int getTicket(){        //同步代码块,以票池本身作为锁旗标        synchronized(this){            int temp = tickets;            tickets = tickets-1;            return temp>0 ? temp : 0;           }    }}

结果:
这里写图片描述
没有出现重复卖票。

变形,方法上锁:
测试代码块16:

public class ThreadDemo7{    public static void main(String[] arg){        TicketPool pool = new TicketPool();        Saler s1 = new Saler("s1",pool);        Saler s2 = new Saler("s2",pool);        Saler s3 = new Saler("s4",pool);        Saler s4 = new Saler("s4",pool);        s1.start();        s2.start();        s3.start();        s4.start();    }}//售票员class Saler extends Thread{    private String name;    private TicketPool pool;    public Saler(String name,TicketPool pool){        this.name = name;        this.pool = pool;    }    public void run(){        while(true){            int no = pool.getTicket();            if(no==0){                return;            }            else{                System.out.println(name+":"+no);            }        }    }}class TicketPool{    private int tickets = 100;    public synchronized int getTicket(){        //同步代码块,以票池本身作为锁旗标        //synchronized(this){            int temp = tickets;            tickets = tickets-1;            return temp>0 ? temp : 0;           //}    }}

结果:
这里写图片描述
这样也是没有问题的。

==========================

7、同步方法是以当前所在对象做锁旗标

synchronized(this)===同步方法

8、同步静态方法,使用类作为同步标记
jvm
*.class加载进入内存的方法区,

public class ThreadDemo7{    public static void main(String[] arg){        TicketPool pool = new TicketPool();        Saler s1 = new Saler("s1");        Saler s2 = new Saler("s2");        Saler s3 = new Saler("s4");        Saler s4 = new Saler("s4");        s1.start();        s2.start();        s3.start();        s4.start();    }}//售票员class Saler extends Thread{    private String name;    private TicketPool pool;    public Saler(String name){        this.name = name;    }    public void run(){        while(true){            int no = TicketPool.getTicket();            if(no==0){                return;            }            else{                System.out.println(name+":"+no);            }        }    }}class TicketPool{    private static int tickets = 100;    public static synchronized int getTicket(){        //同步代码块,以票池本身作为锁旗标        //synchronized(this){            int temp = tickets;            tickets = tickets-1;            return temp>0 ? temp : 0;           //}    }}

结果:
这里写图片描述

===========================

9、wait
让当前线程进入锁旗标的等待队列。释放cpu抢占权,还释放锁旗标的监控权

原创粉丝点击