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

    Java实现多线程有两种方法,一是继承Thread类,二是实现Runnable接口。

    继承Thread类

    继承Thread类,并重写Thread类中的run()方法。调用父类 Thread中start()方法启动线程。

    继承Thread类实例:

    public class Q {
        public static void main(String[] args) {
            //创建一个A类的实例对象
            A a = new A();
            //启动线程
            a.start();
            //main函数
            System.out.println("main method");
        }
    }
    
    class A extends Thread{
        public void run(){
            System.out.println("Hello World!");
        }
    }

    运行结果:
    main method
    Hello World!
    表明两个线程运行完毕。

    上面的例子使用了自定义的类继承Thread类来实现多线程,还有更简单的方式,先前不需要定义一个类继承Thread类,直接使用Thread类本身,并重写Thread类中的run()方法来实现多线程。实例如下:

    public class Q {
        public static void main(String[] args) {
            //创建一个Thread类的实例,在创建时重写run()方法。
            Thread t = new Thread(){
                public void run(){
                    System.out.println("Thread类的线程");
                }
            };
            t.start();
            System.out.println("main方法的线程");
        }
    }

    运行结果如下:
    main方法的线程
    Thread类的线程

    实现Runnable接口

    实现Runnable接口主要是为了解决单继承所带来的不便。

    首先我们来看一下Thread类其中的一个构造方法:

    public Thread(Runnable target) {
        init(null, target, "Thread-" + nextThreadNum(), 0);
    }

    显然,此构造方法接受Runnable类型的参数。所以,所有实现Runnable的类都可以作为参数传递给Thread类的构造方法中。实例如下:

    public class Q {
        public static void main(String[] args) {
            //创建一个A类的实例
            A a = new A();
            //创建一个Thread类对象
            Thread t = new Thread(a);
            //开启线程
            t.start();
            System.out.println("main method");
        }
    }
    
    class A implements Runnable{
        public void run(){
            System.out.println("实现Runnable接口实现多线程");
        }
    }

    运行结果如下:
    main method
    实现Runnable接口实现多线程

    当然,我们要活学活用,或许我们可以不用传入实现Runnable的类的实例,而是传入继承了Thread类的实例作为参数。Thread类本身已经实现了Runnable接口,所以Thread类的构造方法可以接收Thread类本身以及Thread类的子类、实现Runnable接口的类。我们可以通过一个继承了Thread类的类的实例来作为参数传递给Thread类的构造方法中。实例如下:

    public class Q {
        public static void main(String[] args) {
            //创建一个A类的实例对象
            A a = new A();
            //创建一个Thread类的实例
            Thread t = new Thread(a);
            //启动线程
            a.start();
            //main函数
            System.out.println("main method");
        }
    }
    
    class A extends Thread{
        public void run(){
            System.out.println("Hello World!");
        }
    }

    运行结果:
    main method
    Hello World!

    大家可以和通过A类的实例a直接启动线程的方式做一下比较,两种方式的效果完全相同。

    还可以通过匿名内部类的方式实现多线程,注意,匿名内部类的类不是class的意思,是type的意思,意味着类和接口都可以作为匿名内部类。实例如下:

    public class Q {
        public static void main(String[] args) {
            //创建一个Thread类对象,构造方法传入匿名的Runnable接口,必须重写Runnable接口的方法。
            Thread t = new Thread(new Runnable(){
                public void run(){
                    System.out.println("Anonymous inner type");
                }
            });
            System.out.println("main method");
        }
    }

    synchronized关键字

    synchorized修饰方法,称为同步方法;修饰代码块,称为同步代码块。

    首先我们来看一个没有使用synchronized关键字的多线程程序:

    public class Q {
        public static void main(String[] args) {
            //创建一个A对象
            A a = new A();
            //创建两个线程t1、t2,共享a对象,线程名字取不同
            Thread t1 = new Thread(a, "线程1");
            Thread t2 = new Thread(a, "线程2");
            t1.start();
            t2.start();
        }
    }
    
    class A implements Runnable{
    
        int num = 10;
    
        public void run(){
            while (num > 0) {
                System.out.println(Thread.currentThread().getName()+",num = "+num);
                num--;
            }
        }
    }

    运行结果:
    线程1,num = 10
    线程2,num = 10
    线程1,num = 9
    线程2,num = 8
    线程1,num = 7
    线程2,num = 6
    线程1,num = 5
    线程2,num = 4
    线程1,num = 3
    线程2,num = 2
    线程1,num = 1

    线程t1、t2本身是共享一个对象的成员变量num的,但打印出两个线程都为10的状况,这就是没有使用synchronized关键字所出现的问题。

    使用过后的状况(以synchronized同步代码块为例):

    public class Q {
        public static void main(String[] args) {
            //创建一个A对象
            A a = new A();
            //创建两个线程t1、t2,共享a对象,线程名字取不同
            Thread t1 = new Thread(a, "线程1");
            Thread t2 = new Thread(a, "线程2");
            t1.start();
            t2.start();
        }
    }
    
    class A implements Runnable{
    
        int num = 100;
    
        public void run(){
            while (true) {
                synchronized (this) {
                    if (num > 0) {
                        System.out.println(Thread.currentThread().getName()+",num = "+num);
                        num--;
                    } else {
                        break;
                    }
                }
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }
  • 相关阅读:
    快速排序
    Java LinkedList
    Java ArrayList
    Java ReentrantLock
    Java Timer
    Java 管道PipedInputStream PipedOutStream PipedReader PipedWriter
    6. Samba服务和防火墙配置笔记
    5. 网络配置与FTP服务笔记
    3.vi 和软件安装
    2 . Linux常见命令
  • 原文地址:https://www.cnblogs.com/wanxi/p/6476245.html
Copyright © 2011-2022 走看看