码迷,mamicode.com
首页 > 编程语言 > 详细

Java——多线程

时间:2019-08-05 13:44:33      阅读:92      评论:0      收藏:0      [点我收藏+]

标签:cat   get   解锁   ati   路径   类型   img   err   性能   

一、进程/线程:

  1.进程:是一个正在执行的程序;进程是资源管理的最小单位;

    //每一个进程执行都有一个执行顺序;该顺序是一个执行路径,或者叫一个执行单元;

  2.线程:是进程中一个独立的控制单元;线程不能管理资源;

    //线程在控制着进程的执行;

  PS:一个进程中至少有一个线程;

 二、创建线程的两种方式:

  1、继承Thread类:

  (1)定义类继承Thread;

  (2)复写Thread中的run方法;

  (3)创建类继承Thread的类对象;

  (4)调用线程的start()方法:1)启动线程;2)调用run方法;

  PS:1)如果不使用start(),而使用run(),则为正常调用函数,不开启线程;

   2)start()仅仅是通知线程开始,只有争取到时间片后才开始运行;

public class ThreadTest {
    public static void main(String args[]) {
        MyThread mt1 = new MyThread();
        MyThread mt2 = new MyThread();
        mt1.start();
        mt2.start();
        for (int i = 0; i < 100; i++) {
            System.out.println("主线程:"+i);
        }
        System.out.println("执行完成");
    }
}
class MyThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(this.getName() + ":" + i);
        }
    }
}

   2、实现runnable接口:

  (1)定义类实现(implements)Runnable接口;

  (2)覆盖Runnable中的run方法;

  (3)通过Thread类建立线程对象;

  (4)将Runnable接口中的子类对象作为实际参数传递给Thread类的构造函数;

    //传入对象是为了让Thread执行指定的run方法;

  (5)调用Thread类的start方法开启线程并调用Runnable接口子类的run方法;

public class RunnableTest {
    public static void main(String args[]) {
        Runnable myThread = new MyThread();
        Thread thread1 = new Thread(myThread);
        Thread thread2 = new Thread(myThread);
        thread1.start();
        thread2.start();
        System.out.println("执行结束");
    }
}
class MyThread implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + ":" + i);
        }
    }
}

   3、实现和继承两种方式的区别:

    (1)java为单继承,继承Thread后,则无法再继承其他类;

    (2)继承的线程代码存放在Thread的子类中;实现的线程代码存放在接口的子类中;

  4、两种方式的匿名实现:

public class Test {
    public static void main(String[] args) {
        //匿名继承Thread类
        demo1();
        //匿名实现Runnable接口
        demo2();
    }

    private static void demo1() {
        // new一个类(){},继承Thread这个类
        new Thread() {
            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    System.out.println(this.getName() + ":" + i);
                }
            }
        }.start();
    }

    private static void demo2() {
        //将Runnable的子类对象当作参数传递给Thread的构造方法;new Runnable(){}:实现Runnable接口;
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    System.out.println(Thread.currentThread().getName() + ":" + i);
                }
            }
        }).start();
    }
}

三、线程方法:

  (1).getName();获得线程的名称;(用于继承时获取线程名)//this.getName()

  (2)Thread.currentThread();获取创建当前线程的对象;==this;(用于实现时获取线程名)//Thread.currentThread().getName();

  (3)设置线程的名称:1)构造函数传入name;2)setName;

  (4)obj.join();让指定线程加入执行,当前线程进入就绪状态不再执行,但是其他进程还是会抢时间片;加入的指定线程执行完后,当前线程开始执行;

public class RunnableTest {
    public static void main(String args[]) throws InterruptedException {
        Runnable myThread = new MyThread();
        Thread thread1 = new Thread(myThread);
        Thread thread2 = new Thread(myThread);
        thread1.start();
        thread2.start();
        for (int i = 0; i < 100; i++) {
            thread1.join();
            System.out.println("主线程:"+i);
        }
        System.out.println("执行结束");
    }
}
class MyThread implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + ":" + i);
        }
    }
}

  (5)obj.sleep(毫秒[,纳秒]);休眠;休眠状态结束后进入就绪状态;

  (6)obj.yield();让出时间片;线程进入到就绪状态;

    //yield进入到就绪状态,还会争抢时间片,所有yield之后可能还是它第一个运行;

四、多线程状态:

  技术图片

五、多线程安全问题

  (1)问题原因:多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,另一个线程参与进来执行,导致共享数据错误;

  (2)解决办法:对多条操作共享数据的语句,只能让一个线程都执行完。再让其它线程进入;

public class Test {
    public static void main(String args[]) {
        Runnable myThread = new MyThread();
        Thread thread1 = new Thread(myThread);
        Thread thread2 = new Thread(myThread);
        thread1.start();
        thread2.start();
    }
}

class MyThread implements Runnable {
    private int num = 100;

    @Override
    public void run() {
        while (true) {
            if (num > 0) {
                try {
                    Thread.sleep(10);
                } catch (Exception e) {
                }
                num--;
                System.out.println(Thread.currentThread().getName() + ":" + num);
            }
        }
    }
}

六、同步代码块synchronized

  (1)同步代码块:synchronized(对象){需要被同步的代码};

  (2)同步方法:访问修饰符 synchronized 返回值类型 方法名(){};

    //区别:同步代码块可以指定锁;同步方法的锁只能是this;

    //同步前提:1)两个或以上多线程;2)同一个对象()

  (3)缺点:

    1)死锁:请求互斥 请求保持 不可剥夺 形成环路;

    2)性能低;

    3)无法灵活的加锁,解锁;

 1)同步方法:

public class Test {
    public static void main(String args[]) {
        Runnable myThread = new MyThread();
        Thread thread1 = new Thread(myThread);
        Thread thread2 = new Thread(myThread);
        thread1.start();
        thread2.start();
    }
}

class MyThread implements Runnable {
    private int num = 100;

    @Override
    public synchronized void run() {
        while (true) {
            if (num > 0) {
                try {
                    Thread.sleep(10);
                } catch (Exception e) {
                }
                num--;
                System.out.println(Thread.currentThread().getName() + ":" + num);
            }
        }
    }
}

2)同步代码块:

public class Test {
    public static void main(String args[]) {
        Runnable myThread = new MyThread();
        Thread thread1 = new Thread(myThread);
        Thread thread2 = new Thread(myThread);
        thread1.start();
        thread2.start();
    }
}

class MyThread implements Runnable {
    private int num = 100;

    @Override
    public void run() {
        while (true) {
            synchronized (MyThread.class) {
                if (num > 0) {
                    try {
                        Thread.sleep(10);
                    } catch (Exception e) {
                    }
                    num--;
                    System.out.println(Thread.currentThread().getName() + ":" + num);
                }
            }
        }
    }
}

 

Java——多线程

标签:cat   get   解锁   ati   路径   类型   img   err   性能   

原文地址:https://www.cnblogs.com/Tractors/p/11302389.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!