美文网首页
Java-多线程(一)

Java-多线程(一)

作者: 浮桥小麦 | 来源:发表于2017-06-22 17:02 被阅读10次
    NO.1 多线程简介
    1.多线程是CPU不断在执行程序之间切换,速率极快,
    给人们造成的假象是所有程序是同时执行的。 其实在内部依然是一个个执行的。
    2. JVM的启动是多线程的
    //证明JVM是多线程的
    
            //创建垃圾
            for (int i = 0; i < 1000000; i++){
                new Test();
            }
            //主线程
            for (int i = 0; i < 10000; i++){
                System.out.println("我是主线程");
            }
        }
    }
    class Test {
       @Override
        public void finalize(){
           System.out.println("垃圾被回收了");
       }
    }
    
    
    
    NO.2 多线程实现方式(一)
      MyThread mt = new MyThread();//创建线程的子类对象
             // mt.run();
             mt.start();//开启线程
             //为了看效果,我们在主线程中也写点东西
            for (int i = 0; i < 10000; i++){
                System.out.println("kobekobekobe");
            }
            //执行后,如果是开辟了新的线程,那么这两个打印应该时交替打印的
            //结果却没有,是因为我们的方法没调用好。应该是用start方法开启线程
         }
    }
    class MyThread extends Thread {//1.继承Thread
      //2.重写run方法
        public  void run(){
            //3.将自己想执行的代码放这里面
            for (int i = 0; i < 10000; i++){
                System.out.println("tmactmactmac");
            }
        }
    }
    
    
    NO.3 多线程实现方式(二)
     MyThread mt = new MyThread();
            //Runnable接口中只有一个run方法,没有启动线程的方法,需要借助于Thread类
            Thread tr = new Thread(mt); //用Thread的构造方法将实现了Runnable接口的类作为参数
            tr.start();
     //主线程方法
            for (int i = 0; i < 10100; i++){
                System.out.println("bbbbbbbbbbbbbbbbbb");
            }
        }
    }
    class MyThread implements Runnable {//1.实现Runnable接口
        //2.重写run方法
        public void run(){
            for (int i = 0; i < 10000; i++){
                System.out.println("aaaaaaaaaaaaaaaaaaaaaaaaaaa");
            }
        }
    }
    
    NO.4 匿名内部类实现线程的两种方式
    //匿名内部类实现多线程方式一:继承Thread
            new Thread() { //1.继承Thread类
                public void run() {//2.重写run方法
                    for (int i = 0; i < 10000; i++) {
                        System.out.println("aaaaaaaaaaa");
                    }
                }
            }.start();//调用start方法开启线程
    
            //主线程方法
            for (int i = 0; i < 100000; i++){
                System.out.println("bbbbbb");
            }
    
     // //匿名内部类实现多线程方式二:Runnable实现
            //写好后将整个new Runnable作为一个参数传给Thread
            new Thread(new Runnable() {
                public void run(){
                    for (int i = 0; i < 100000; i++) {
                        System.out.println("cccccccccccccccccccc");
                    }
                }
            }).start();
    
    
    
    NO.5 多线程获取名字和设置名字
     //多线程取名和设置名称
            //创建一条线程
            //通过构造方法给线程命名
            new Thread("JJ的线程") {
                public void run() {
                    //this.getName():获取线程名
                    System.out.println( this.getName() +  " -aaaaaaaaaaa");
                }
            }.start();
            //创建另一条线程
            new Thread("麦迪的线程") {
                public void run() {
                    System.out.println( this.getName() +  " -bbbbbb");
                }
            }.start();
            //打印结果:Thread-0 -aaaaaaaaaaa
            //Thread-1 -bbbbbb
    
            //setName给线程取名
            MyThread mr = new MyThread();
            mr.setName("科比的线程");
            mr.start();
        }
    }
    class MyThread extends Thread {//1.实现Runnable接口
        //2.重写run方法
        public void run(){
            System.out.println(this.getName() + "-ccccccc");
        }
    }
    
    
    NO.6 获取当前线程对象
     //获取当前线程
            //通过构造方法给线程命名
            new Thread("JJ的线程") {
                public void run() {
                    System.out.println( this.getName() +  " -aaaaaaaaaaa");
                }
            }.start();
            //创建另一条线程
    
            Thread tr = new Thread( new Runnable() {
                public void run(){
                    //Thread.currentThread()就是获得当前线程
                    System.out.println(Thread.currentThread().getName() +  "-bbbb");
                }
            });
            tr.setName("麦迪的线程");
            tr.start();
    
            //当然也可以设置主线程名字
            Thread.currentThread().setName("我是主线程");
            //再打印一下主线程的线程--在主方法中调用的就是主线程
            System.out.println(Thread.currentThread().getName());
    
    
    NO.7 休眠线程
    //休眠线程
    //        for (int i = 20; i >= 0; i--){
    //            //调用休眠方法--这里要抛出一个中断异常
    //            Thread.sleep(1000);//这里面传入的是毫秒值
    //            System.out.println("倒计时" + i + "秒");
    //        }
    
            //在自己的线程中用sleep
            new Thread(){
                public void run(){
                    for (int i = 20; i >= 0; i--){
                        //调用休眠方法--这里要抛出一个中断异常
                        try {
                            this.sleep(1000);//这里面传入的是毫秒值
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println("倒计时" + i + "秒");
                    }
                }
            }.start();
    
    
    NO.8 守护线程
     //守护线程:这样理解守护线程相当于象棋中的其他棋子,然后非守护线程就相当于将
            //当将死亡(执行完),那么守护线程也就得直接挂掉了
            Thread t1 = new Thread() {
                public void  run(){
                    for (int i = 0; i < 2; i++){
                        System.out.println(this.getName() + "----111111");
                    }
                }
            };
            t1.setName("t1的线程");
            Thread t2 = new Thread() {
                public void  run(){
                    for (int i = 0; i < 10; i++){
                        System.out.println(this.getName() + "----22");
                    }
                }
            };
            t2.setName("t2的线程");
    
            //按照上面的理解,我们将t2设置为守护线程,这样当t1执行完后,t2也就随之挂掉了
            t2.setDaemon(true);
            t1.start();
            t2.start();
    
    
    NO.9 加入线程
     //加入线程--相当于插队,插入的线程要先执行完了,被插入线程才能执行
    
           final Thread t1 = new Thread() {
                public void  run(){
                    for (int i = 0; i < 10; i++){
                        System.out.println(this.getName() + "----111111");
                    }
                }
            };
            t1.setName("t1的线程");
    
    
            Thread t2 = new Thread() {
                public void  run(){
                    for (int i = 0; i < 10; i++){
                        if (i == 3){
                            try {
                                t1.join();//将t1线程插t2线程的执行中
                                //t1.join(10000);还可以指定插入线程的执行时间,过了这个时间,线程间还是交替执行
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
    
                        System.out.println(this.getName() + "----22");
                    }
                }
            };
            t2.setName("t2的线程");
            t1.start();
            t2.start();
    
    
    NO.10 礼让线程
     //礼让线程--只作了解
            Thread t1 = new Thread() {
                public void run(){
    
                    for (int i = 0; i < 500; i++){
                        System.out.println(this.getName() + "线程在执行");
                    }
                }
            };
    
            MyThread mt = new MyThread();
            mt.start();
            t1.start();
        }
    }
    class MyThread extends Thread {//1.实现Runnable接口
        //2.重写run方法
        public void run(){
           for (int i = 1; i <= 1000; i++){
                if (i % 10 == 0 ){
    
               Thread.yield();//只要是10的倍数,这个线程就让出cpu
                    System.out.println(this.getName() + "线程在让出cpu");
                }else{
                    System.out.println(this.getName() + "-ccccccc");
                }
    
           }
    
        }
    }
    
    
    NO.11 设置线程优先级
    //线程优先级
            Thread t1 = new Thread() {
                public void run(){
    
                    for (int i = 0; i < 10; i++){
                        System.out.println(this.getName() + "线程在执行");
                    }
                }
            };
    
            Thread t2 = new Thread() {
                public void run(){
    
                    for (int i = 0; i < 10; i++){
                        System.out.println(this.getName() + "线程在执行");
                    }
                }
            };
    
            t1.setPriority(1);//线程优先级范围1-10之间//10最高
            t2.setPriority(10);//设置优先级,不是说要一个线程执行完了,另一个线程才能执行。
            //只是一个线程获得cpu的执行次数要多些而已
            t2.start();
            t1.start();
    
    
    NO.12 线程同步代码块
    //线程同步代码块:当一个线程中要执行多段代码,我们希望这个线程中正在执行的多段代码
            //不要受到线程切换的影响,就需要给加一个同步代码块,这样保证一个线程中的一次执行能够完整的完成
           final  Printer p1 = new Printer();
           //为什么这个Printer前面要有个final修饰符
            //因为p1在匿名内部类中使用了,作为匿名内部类的局部变量,必须用final修饰
             //创建线程
            new Thread() {
                public void run(){
                    int i = 100000000;
                    while (i>0){//不断调用p1中的方法
                        p1.print();
                        i--;
                    }
                }
            }.start();
    
            new Thread() {
                public void run(){
                    int i = 10;
                    while (i>0) {//不断调用p1中的方法
                        p1.print2();
                        i--;
                    }
                }
            }.start();
        }
    }
    //打印机类
    class Printer {
        Test test = new Test();//所对象可以是任意的,且两个锁的对象得是一样的
        public  void print(){
            synchronized (test){//同步代码块,锁对象:其中要传入的所对象,可以是任意的,但是不能是匿名对象
                System.out.print("C");
                System.out.print("罗");
                System.out.print("威");
                System.out.println("武");
            }
    
        }
        public  void print2(){
            synchronized (test){
                System.out.println("我是小菜鸟");
            }
        }
    }
    class Test {}
    
    
    NO.13 多线程的同步方法
    /**
         * @param args
         * 同步代码块
         */
        public static void main(String[] args) {
            final Printer2 p = new Printer2();
            
            new Thread() {
                public void run() {
                    while(true) {
                        p.print1();
                    }
                }
            }.start();
            
            new Thread() {
                public void run() {
                    while(true) {
                        p.print2();
                    }
                }
            }.start();
        }
    
    }
    
    class Printer2 {
        Demo d = new Demo();
        //非静态的同步方法的锁对象是神马?
        //答:非静态的同步方法的锁对象是this
        //静态的同步方法的锁对象是什么?
        //是该类的字节码对象
        public static synchronized void print1() {                          //同步方法只需要在方法上加synchronized关键字即可
            System.out.print("黑");
            System.out.print("马");
            System.out.print("程");
            System.out.print("序");
            System.out.print("员");
            System.out.print("\r\n");
        }
        
        public static void print2() {
            //synchronized(new Demo()) {                            //锁对象不能用匿名对象,因为匿名对象不是同一个对象
            synchronized(Printer2.class) {      
                System.out.print("传");
                System.out.print("智");
                System.out.print("播");
                System.out.print("客");
                System.out.print("\r\n");
            }
        }
    }
    
    
    NO.14 线程安全问题--卖票例子
     //练习铁路窗口:一共100张票,通过4个窗口卖完
            //多线程并发操作同一数据时,就有可能出现线程安全问题
            //使用同步技术可以解决这种问题,把操作数据的代码进行同步,不要多个线程一起操作
            //开启四条线程购票
            new Ticket().start();
            new Ticket().start();
            new Ticket().start();
            new Ticket().start();
            //我们这样操作,就成了每一个窗口都有100张票,各卖各的了
            //我们的初衷是四个窗口共同一起卖100张票
            //我们可以将这100张票弄成类变量,就成了四个对象公有的了
        }
    }
    
    class  Ticket extends Thread {
    
        private static int ticket = 100;//这是100张火车票
         public  void run(){
            synchronized (Ticket.class) {//加锁
                while (true) {
    
                    if (ticket ==  0) {//票卖完了,我们就跳出这个循环
                        System.out.println("票卖完了");
                        break;
                    }
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(this.getName() + "--这是第" + ticket-- + "号票");
    
                }
            }
    
         }
    }
    
    
    NO.15 上面例子用Runnable实现
    /**
         * @param args
         * 火车站卖票的例子用实现Runnable接口
         */
        public static void main(String[] args) {
            MyTicket mt = new MyTicket();
            new Thread(mt).start();
            new Thread(mt).start();
            new Thread(mt).start();
            new Thread(mt).start();
            
            /*Thread t1 = new Thread(mt);               //多次启动一个线程是非法的
            t1.start();
            t1.start();
            t1.start();
            t1.start();*/
        }
    
    }
    
    class MyTicket implements Runnable {
        private int tickets = 100;
        @Override
        public void run() {
            while(true) {
                synchronized(this) {
                    if(tickets <= 0) {
                        break;
                    }
                    try {
                        Thread.sleep(10);               //线程1睡,线程2睡,线程3睡,线程4睡
                    } catch (InterruptedException e) {
                        
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "...这是第" + tickets-- + "号票");
                }
            }
        }
    }
    
    
    NO.16 多线程死锁
    /**
         * @param args
         */
        private static String s1 = "筷子左";
        private static String s2 = "筷子右";
    
        public static void main(String[] args) {
            new Thread() {
                public void run() {
                    while(true) {
                        synchronized(s1) {
                            System.out.println(getName() + "...获取" + s1 + "等待" + s2);
                            synchronized(s2) {
                                System.out.println(getName() + "...拿到" + s2 + "开吃");
                            }
                        }
                    }
                }
            }.start();
            
            new Thread() {
                public void run() {
                    while(true) {
                        synchronized(s2) {
                            System.out.println(getName() + "...获取" + s2 + "等待" + s1);
                            synchronized(s1) {
                                System.out.println(getName() + "...拿到" + s1 + "开吃");
                            }
                        }
                    }
                }
            }.start();
        }
    }
    
    

    相关文章

      网友评论

          本文标题:Java-多线程(一)

          本文链接:https://www.haomeiwen.com/subject/wrxtcxtx.html