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

    线程要依附进程存在

    多线程的实现一定要有一个线程的主类,而主类往往需要操作一些资源,但对于多线程主类的实现有一定的要求:

    1. 继承Thread父类;

    2. 实现Runnable接口(Callable接口)

    继承Thread类实现多线程:

    在java.lang包有Thread类,子类继承Thread后要覆写Thread类中的run()方法,这个方法就属于线程的主方法。

     定义:public void run();

    范例:线程的主体类;

    class MyThread extends Thread{ //表示实现多线程
        private String name;
        public MyThread(String name) { //线程的名字
            this.name = name;
        }
        @Override
        public void run() { //覆写run()方法,线程的主方法
            for(int x = 0; x < 10; x++) {
                System.out.println(this.name + ", x = " + x);
            }
        }
    }

    上面是将内容输出10次,所有的线程并发执行,即在一个时间段上会有多个线程交替执行,所以不能直接调用run方法,而应该调用Thread类中的start()方法启动多线程。

    public void start()

    范例:启动多线程 

    class MyThread extends Thread{ //表示实现多线程
        private String name;
        public MyThread(String name) { //线程的名字
            this.name = name;
        }
        @Override
        public void run() { //覆写run()方法,线程的主方法
            for(int x = 0; x < 10; x++) {
                System.out.println(this.name + ", x = " + x);
            }
        }
    }
    public class Hello{
        public static void main(String[] args) {
            MyThread mt1 = new MyThread("线程A");
            MyThread mt2 = new MyThread("线程B");
            MyThread mt3 = new MyThread("线程C");
            mt1.start();
            mt2.start();
            mt3.start();
        }    
    }

    结果混乱,是因为交替执行,没有固定的执行顺序。若不调用start而调用run,就是顺序执行 

    实现Runnable接口

    继承Thread会有单继承的局限,所以最好的做法是利用接口来解决,于是使用Runnable接口。

    public interface Runnable {
        public void run();    
    }

    按照正常思路实现Runnable多线程:

    class MyThread implements Runnable{ //表示实现多线程
        private String name;
        public MyThread(String name) { //线程的名字
            this.name = name;
        }
        @Override
        public void run() { //覆写run()方法,线程的主方法
            for(int x = 0; x < 10; x++) {
                System.out.println(this.name + ", x = " + x);
            }
        }
    }

    此时如果想开始多线程,由于现在实现的是Runnable接口,所以无法用Thread类中的start方法了,现在使用匿名内部类来使用start方法

    class MyThread implements Runnable{ //表示实现多线程
        private String name;
        public MyThread(String name) { //线程的名字
            this.name = name;
        }
        @Override
        public void run() { //覆写run()方法,线程的主方法
            for(int x = 0; x < 10; x++) {
                System.out.println(this.name + ", x = " + x);
            }
        }
    }
    public class Hello{
        public static void main(String[] args) {
            MyThread mt1 = new MyThread("线程A");
            MyThread mt2 = new MyThread("线程B");
            MyThread mt3 = new MyThread("线程C");
            new Thread(mt1).start();  //匿名
            new Thread(mt2).start();
            new Thread(mt3).start();
        }    
    }

    面试题

    继承Thread类和Runnable接口两种实现方式的区别:

      多线程一定需要一个线程的主类,要么继承Thread类,要么实现Runnable接口

      使用Runnable接口可以比Thread更好实现数据共享操作,利用Runnable接口可以避免单继承局限问题

      

    Thread类实现了Runnable接口。

    Runnable接口实现的多线程要比Thread类实现的多线程更方便的表现出数据共享的概念

    范例:希望有三个线程进行买票 - Thread实现会发现三个线程各自卖各自的票,票没有了其他线程也不知道

    class MyThread extends Thread{ //表示实现多线程
        private int ticket = 5;
        
        @Override
        public void run() { //覆写run()方法,线程的主方法
            for(int x = 0; x < 50; x++) {
                if(this.ticket>0) {
                    System.out.println("卖票,ticket = " + this.ticket --);
                }
            }
        }
    }
    public class Hello{
        public static void main(String[] args) {
            MyThread mt1 = new MyThread();
            MyThread mt2 = new MyThread();
            MyThread mt3 = new MyThread();
            mt1.start();
            mt2.start();
            mt3.start();
        }    
    }

    使用Runnable接口实现:

    class MyThread implements Runnable{ //表示实现多线程
        private int ticket = 5;
        
        @Override
        public void run() { //覆写run()方法,线程的主方法
            for(int x = 0; x < 50; x++) {
                if(this.ticket>0) {
                    System.out.println("卖票,ticket = " + this.ticket --);
                }
            }
        }
    }
    public class Hello{
        public static void main(String[] args) {
            MyThread mt = new MyThread();
            new Thread(mt).start();
            new Thread(mt).start();
            new Thread(mt).start();
        }    
    }

    Callable接口:

    比Runnable的好处是可以返回值

    class MyThread implements Callable<String>{ //表示实现多线程
        private int ticket = 5;
        
        @Override
        public String call() { //覆写run()方法,线程的主方法
            for(int x = 0; x < 50; x++) {
                if(this.ticket>0) {
                    System.out.println("卖票,ticket = " + this.ticket --);
                }
            }
            return "票卖完了";
        }
    }
    public class Hello{
        public static void main(String[] args) throws InterruptedException, ExecutionException {
            Callable<String> cal = new MyThread();
            FutureTask<String> task = new FutureTask<>(cal);
            Thread thread = new Thread(task);
            thread.start();
            System.out.println(task.get()); //取得线程主方法的返回值
        }    
    }

    线程休眠

    可以让某些线程延缓执行

    休眠方法:public static void sleep (long millis) throws InterruptedException;

    如果休眠时间没到就停止休眠了,那么就会产生中断异常。

    Thread.sleep(1000);  加上这一句,延迟一秒,会有报错,点报错纠错就对了

    class MyThread implements Runnable{ //表示实现多线程    
        @Override
        public void run() { //覆写run()方法,线程的主方法
            for(int x = 0; x < 100; x++) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }  //休眠一秒
                System.out.println(Thread.currentThread().getName() + ", x = " + x);
            }
        }
    }
    public class Hello{
        public static void main(String[] args) throws InterruptedException, ExecutionException {
            MyThread mt = new MyThread();
            new Thread(mt, "线程A").start();
            new Thread(mt, "线程B").start();
            new Thread(mt, "线程C").start();
        }    
    }

    线程的优先级

    优先级越高的线程越有可能先执行,而在Thread类定义一下优先级方法

      设置优先级:public final void setPriority(int newPriority);

      取得优先级:public final int getPriority();

    优先级定义有三种:

    最高优先级:public static final int MAX_PRIORITY,10;

    中等优先级:public static final int NORM_PRIORITY,5;

    最低优先级:public static final int MIN_PRIORITY,1;

    class MyThread implements Runnable{ 
        @Override
        public void run() { 
            for(int x = 0; x < 100; x++) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }  
                System.out.println(Thread.currentThread().getName() + ", x = " + x);
            }
        }
    }
    public class Hello{
        public static void main(String[] args) throws InterruptedException, ExecutionException {
            MyThread mt = new MyThread();
            Thread t1 = new Thread(mt, "线程A");
            Thread t2 = new Thread(mt, "线程B");
            Thread t3 = new Thread(mt, "线程C");
            t1.setPriority(Thread.MAX_PRIORITY);
            t2.setPriority(Thread.MIN_PRIORITY);
            t3.setPriority(Thread.MIN_PRIORITY);
            t1.start();
            t2.start();
            t3.start();
        }    
    }

    设置优先级只是理论上的,不一定真的就是优先

    范例:主线程的优先级是什么

    public class Hello{
        public static void main(String[] args) throws InterruptedException, ExecutionException {
            System.out.println(Thread.currentThread().getPriority());
        }    
    }

    结果是5,主线程属于中等优先级

    总结:

    线程要有名字,Thread.currentThread取得当前线程;

    线程的休眠有先后顺序

    优先级越高理论上越有可能先执行

    线程同步,多线程需要访问同一资源

    同步代码块:使用synchronized关键字定义的代码块就是同步代码块,但同步的时候需要设置一个同步对象,往往使用this同步当前对象。

    范例:买票,买票最后票的数量不能出现负数

    class MyThread implements Runnable{
        private int ticket = 50;
        @Override
        public void run() {
            for(int x = 0; x < 100; x ++) {
                synchronized (this) { //同步代码块
                    if(this.ticket > 0) {
                        try {
                            Thread.sleep(100); //延迟一秒
                        }
                        catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName() + ", ticket = " + this.ticket --);
                    }
                }
            }
        }
    }
    
    
    public class Hello{
        public static void main(String[] args) throws Exception {
            MyThread mt = new MyThread();
            Thread t1 = new Thread(mt,"票贩子A");
            Thread t2 = new Thread(mt,"票贩子B");
            Thread t3 = new Thread(mt,"票贩子C");
            t1.start();
            t2.start();
            t3.start();
        }
    }

     另一种实现方式,synchronized方法

    class MyThread implements Runnable{
        private int ticket = 5;
        @Override
        public void run() {
            for(int x = 0; x < 10; x ++) {
                this.sale();
                }
            }
        
        public synchronized void sale() { //卖票
            if(this.ticket > 0) {
                try {
                    Thread.sleep(100); //延迟一秒
                }
                catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + ", ticket = " + this.ticket --);
            }
        }
    }
    
    
    public class Hello{
        public static void main(String[] args) throws Exception {
            MyThread mt = new MyThread();
            Thread t1 = new Thread(mt,"票贩子A");
            Thread t2 = new Thread(mt,"票贩子B");
            Thread t3 = new Thread(mt,"票贩子C");
            t1.start();
            t2.start();
            t3.start();
        }
    }
  • 相关阅读:
    thinkphp 视图定义
    ThinkPHP支持模型的分层
    thinkphp 虚拟模型
    thinkphp 参数绑定
    thinkphp 自动完成
    thinkphp 自动验证
    thinkphp 子查询
    thinkphp 动态查询
    ThinkPHP sql查询
    thinkphp 统计查询
  • 原文地址:https://www.cnblogs.com/lonske/p/8798235.html
Copyright © 2011-2022 走看看