zoukankan      html  css  js  c++  java
  • Java多线程

    1.简单Java多线程例子(继承Thread)

    public class hello extends Thread{
        private String name;
                                                                                                                                                                                                                                                                                                                                                           
        public hello(String name) {
            this.name = name;
        }
                                                                                                                                                                                                                                                                                                                                                           
        public void run() {
            for (int i = 0; i < 5; i++) {
                System.out.println(name + "运行..." + i);
            }
        }
                                                                                                                                                                                                                                                                                                                                                           
        public static void main(String[] args) {
            hello hello1 = new hello("A");
            hello hello2 = new hello("B");
            hello hello3 = new hello("C");
            hello1.start();
            hello2.start();
            hello3.start();
        }
    }

    某一次的执行结果为:

    B运行...0

    B运行...1

    B运行...2

    C运行...0

    A运行...0

    C运行...1

    B运行...3

    C运行...2

    A运行...1

    C运行...3

    B运行...4

    C运行...4

    A运行...2

    A运行...3

    A运行...4


    2.简单Java多线程例子(实现Runnable接口)

    public class Test1 implements Runnable {//实现Runnable接口
        private String name;
        public Test1(String name) {
            this.name = name;
        }
        @Override
        public void run() {
            for (int i = 0; i < 5; i++) {
                System.out.println(name + "运行..." + i);
            }
        }
                                                                                                                                                                                                                                                                                                                                        
        public static void main(String[] args) {
            Test1 test1 = new Test1("线程A");
            Thread demo = new Thread(test1);
            Test1 test2 = new Test1("线程B");
            Thread demo1 = new Thread(test2);
            Test1 test3 = new Test1("线程C");
            Thread demo2 = new Thread(test3);
                                                                                                                                                                                                                                                                                                                                            
            demo.start();
            demo1.start();
            demo2.start();
        }
    }

    某一次的执行结果为

    线程A运行...0

    线程A运行...1

    线程A运行...2

    线程B运行...0

    线程B运行...1

    线程A运行...3

    线程C运行...0

    线程A运行...4

    线程B运行...2

    线程B运行...3

    线程C运行...1

    线程B运行...4

    线程C运行...2

    线程C运行...3

    线程C运行...4


    Thread也是实现Runnable接口的,Thread中的run方法调用的是Runnable接口的run方法。Thread和Runnable都实现了run方法,这种操作模式其实就是代理模式。


    Thread和Runnable的区别:

    如果一个类继承Thread,则不适合资源共享。但是如果实现了Runable接口的话,则很容易的实现资源共享。


    如果是一个买票系统,如果count表示的是车票的数量,使用Runnable接口

    public class MyThread implements Runnable{
        private int ticket = 5;
        @Override
        public void run() {
            for (int i = 0; i < 20; i++) {
                if (this.ticket > 0) {
                    System.out.println(Thread.currentThread().getName() + "正在买票" + this.ticket--);
    //              this.ticket--;//不可以分开写,线程级别,会出现不同步...
                }
            }
        }
    }
    public static void main(String[] args) {
        MyThread mt = new MyThread();
        new Thread(mt, "1号窗口").start();
        new Thread(mt, "2号窗口").start();
        new Thread(mt, "3号窗口").start();
    }

    某一次的执行结果为

    1号窗口正在买票5

    3号窗口正在买票3

    2号窗口正在买票4

    3号窗口正在买票1

    1号窗口正在买票2


    总结:

    实现Runnable接口比继承Thread类所具有的优势:

    1):适合多个相同的程序代码的线程去处理同一个资源

    2):可以避免java中的单继承的限制

    3):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立。

    建议尽量使用Runnable接口


    public class Test3 implements Runnable {
        @Override
        public void run() {
            for (int i = 0; i < 3; i++) {
                System.out.println(Thread.currentThread().getName());
            }
        }
        public static void main(String[] args) {
            Test3 test = new Test3();
            new Thread(test, "A").start();
            new Thread(test, "B").start();
            new Thread(test).start();
        }
    }

    某一次的执行结构为

    A

    B

    B

    B

    Thread-0

    Thread-0

    A

    A

    Thread-0



    如果我们没有指定名字的话,系统自动提供名字。

    提醒一下大家:main方法其实也是一个线程。在java中所以的线程都是同时启动的,至于什么时候,哪个先执行,完全看谁先得到CPU的资源。

    在java中,每次程序运行至少启动2个线程。一个是main线程,一个是垃圾收集线程。因为每当使用java命令执行一个类的时候,实际上都会启动一个JVM,每一个JVM实习在就是在操作系统中启动了一个进程。


    判断线程是否启动

    public class Test4 implements Runnable {
        @Override
        public void run() {
            for (int i = 0; i < 3; i++) {
                System.out.println(Thread.currentThread().getName());
            }
        }
        public static void main(String[] args) {
            Test4 test = new Test4();
            Thread demo = new Thread(test);
            System.out.println("线程启动之前---》" + demo.isAlive());
            demo.start();
            System.out.println("线程启动之后---》" + demo.isAlive());
        }
    }

    某一次的执行结果为

    线程启动之前---》false

    线程启动之后---》true

    Thread-0

    Thread-0

    Thread-0


    主线程也有可能在子线程结束之前结束。并且子线程不受影响,不会因为主线程的结束而结束。


    线程的强制执行

    public class Test5 implements Runnable {
        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                System.out.println(Thread.currentThread().getName());
            }
        }
        public static void main(String[] args) {
            Test5 t = new Test5();
            Thread demo = new Thread(t, "线程");
            demo.start();
            for (int i = 0; i < 10; ++i) {
                if (i > 5) {
                    try {
                        demo.join(); // 强制执行demo
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("main 线程执行-->" + i);
            }
        }
    }

    某一次的执行结果为

    main 线程执行-->0

    线程

    线程

    线程

    线程

    线程

    线程

    线程

    线程

    线程

    线程

    main 线程执行-->1

    main 线程执行-->2

    main 线程执行-->3

    main 线程执行-->4

    main 线程执行-->5

    main 线程执行-->6

    main 线程执行-->7

    main 线程执行-->8

    main 线程执行-->9


    线程的休眠

    public class Test6 implements Runnable {
        @Override
        public void run() {
            for (int i = 0; i < 3; i++) {
                try {
                    System.out.println(new Date());
                    Thread.sleep(2000);//休眠2000毫秒
                    System.out.println(new Date());
                } catch (Exception e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + i);
            }
        }
        public static void main(String[] args) {
            Test6 t = new Test6();
            Thread demo = new Thread(t, "线程");
            demo.start();
        }
    }

    某一次的执行结果

    Thu May 15 15:01:11 CST 2014

    Thu May 15 15:01:13 CST 2014

    线程0

    Thu May 15 15:01:13 CST 2014

    Thu May 15 15:01:15 CST 2014

    线程1

    Thu May 15 15:01:15 CST 2014

    Thu May 15 15:01:17 CST 2014

    线程2


    线程的中断

    public class Test7 implements Runnable {
        public void run() {
            System.out.println("执行run方法");
            System.out.println(new Date());
            try {
                Thread.sleep(10000);
                System.out.println("线程完成休眠");
            } catch (Exception e) {
                System.out.println("休眠被打断");
                return; // 返回到程序的调用处
            }
            System.out.println("线程正常终止");
        }
        public static void main(String[] args) {
            Test7 t = new Test7();
            Thread demo = new Thread(t, "线程");
            demo.start();
            try {
                Thread.sleep(2000);
            } catch (Exception e) {
                e.printStackTrace();
            }
            demo.interrupt(); // 2s后中断线程
            System.out.println(new Date());
        }
    }

    某一次的执行结果

    执行run方法

    Thu May 15 15:05:04 CST 2014

    Thu May 15 15:05:06 CST 2014

    休眠被打断


    守护线程

    public class Test8 implements Runnable{
        public void run() {
            while (true) {
                System.out.println(Thread.currentThread().getName() + "在运行");
            }
        }
        public static void main(String[] args) throws InterruptedException {
            Test8 t = new Test8();
            Thread demo = new Thread(t, "线程");
            demo.setDaemon(true);//守护线程:守护线程则是用来服务用户线程的
    //如果没有其他用户线程在运行,那么就没有可服务对象,也就没有理由继续下去。
            demo.start();
            System.out.println("Hello world!!!");
        }
    }

    执行结果

    Hello world!!!

    线程在运行

    线程在运行

    线程在运行

    线程在运行

    线程在运行

    如果没有System.out.println("Hello world!!!");这句,run方法里面的语句不会执行


    线程的优先级

    public class Test9 implements Runnable {
        public void run() {
            for (int i = 0; i < 5; ++i) {
                System.out.println(Thread.currentThread().getName() + "运行" + i);
            }
        }
        public static void main(String[] args) {
            Thread h1 = new Thread(new Test9(), "A");
            Thread h2 = new Thread(new Test9(), "B");
            Thread h3 = new Thread(new Test9(), "C");
            h1.setPriority(8);
            h2.setPriority(2);
            h3.setPriority(6);
            h1.start();
            h2.start();
            h3.start();
        }
    }

    某一次的执行结果

    A运行0

    A运行1

    A运行2

    B运行0

    C运行0

    B运行1

    A运行3

    B运行2

    C运行1

    B运行3

    A运行4

    B运行4

    C运行2

    C运行3

    C运行4

    谁先执行还是取决于谁先去的CPU的资源,主线程的优先级是5


    线程的礼让

    在线程操作中,也可以使用yield()方法,将一个线程的操作暂时交给其他线程执行

    public class Test10 implements Runnable {
        public void run() {
            for (int i = 0; i < 5; ++i) {
                System.out.println(Thread.currentThread().getName() + "运行" + i);
                if (i == 2) {
                    System.out.println("线程的礼让");
                    Thread.currentThread().yield();//将一个线程的操作暂时交给其他线程执行
                }
            }
        }
        public static void main(String[] args) {
            Thread h1 = new Thread(new Test10(), "A");
            Thread h2 = new Thread(new Test10(), "B");
            h1.start();
            h2.start();
        }
    }

    某一次的执行结果

    A运行0

    B运行0

    B运行1

    A运行1

    B运行2

    线程的礼让

    B运行3

    B运行4

    A运行2

    线程的礼让

    A运行3

    A运行4


    线程同步

    在买票的程序中需要考虑线程同步保证数据不出错

    格式

    synchronized(同步对象){
                                                                                      
     //需要同步的代码
                                                                                      
    }


    public class Test11 implements Runnable {
        private int count = 5;
        @Override
        public void run() {
            for (int i = 0; i < 10; ++i) {
                synchronized (this) {//线程同步
                    if (count > 0) {
                        try {
                            Thread.sleep(1000);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        System.out.println(count--);
                    }
                }
            }
        }
        public static void main(String[] args) {
            Test11 t = new Test11();
            Thread thread1 = new Thread(t);
            Thread thread2 = new Thread(t);
            Thread thread3 = new Thread(t);
            thread1.start();
            thread2.start();
            thread3.start();
        }
    }

    执行结果

    5

    4

    3

    2

    1

    每秒钟输一个


    也可以采用同步方法

    语法格式为

    synchronized 方法返回类型方法名(参数列表){
                                                              
        // 其他代码
                                                              
    }

    采用同步方法解决上面的问题

    public class Test12 implements Runnable {
        private int count = 5;
        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                sale();
            }
        }
        public synchronized void sale() {// 同步方法
            if (count > 0) {
                try {
                    Thread.sleep(1000);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                System.out.println(count--);
            }
        }
                                                          
        public static void main(String[] args) {
            Test12 t = new Test12();
            Thread thread1 = new Thread(t);
            Thread thread2 = new Thread(t);
            Thread thread3 = new Thread(t);
                                                              
            thread1.start();
            thread2.start();
            thread3.start();
        }
    }

    执行效果和上面的同步线程完全一样。

    当多个线程共享一个资源的时候需要进行同步,但是过多的同步可能导致死锁。

    经典的生产者和消费者问题············To be continued...

    本文出自 “阿凡达” 博客,请务必保留此出处http://shamrock.blog.51cto.com/2079212/1410738

  • 相关阅读:
    【BIRT】报表数据导出为PDF显示不全
    【BIRT】报表显示不全
    【BIRT】02_开发一张简单的报表
    【BIRT】01_在win10上安装BIRT
    【漫画解读银行业务】
    【FinancialKnowledge】拨备
    虚拟机“锁定文件失败”、“打不开磁盘”或者“它所依赖的某个快照磁盘”的解决办法
    【DB2】DbVisualizer编译存储过程
    【DB2】If 'db2' is not a typo you can run the following command to lookup the package that contains the binary: command-not-found db2 bash: db2: command not found
    【Linux】配置JAVA_HOME环境变量
  • 原文地址:https://www.cnblogs.com/umgsai/p/3908088.html
Copyright © 2011-2022 走看看