zoukankan      html  css  js  c++  java
  • Java多线程之冰山一角

    一.   多线程原理

    线程类:

    //继承线程类,重写run方法

    public class MyThread extends Thread{

        public void run(){

            for (int i = 0; i < 100; i++) {

                System.out.println("i="+i);

            }

        }

    }

    测试类:

    //启动线程

    public class Demo01 {

         //主线程

        public static void main(String [] args){

            //创建子类对象

            MyThread myThread=new MyThread();

            //调用父类的start方法,启动多线程

            myThread.start();

            for (int k = 0; k < 100; k++) {

                System.out.println("k="+k);

            }

        }

    }

    多个线程运行原理:

    1.当主线程启动一个独立了的线程后,这个独立的线程就会与主线程“同时”运行;

    2.对于单颗,单核CUP来说,在某一个时间点上,CPU中只有一个线程在运行(由操作系统分配时间片,时间片用完后切换其他的线程)一段时间。

    二.  1.     创建线程的方式一:继承Thread类及其常用方法

    步骤:

    (1)  自定义线程类,继承Thread

    (2)  重写Thradrun()方法(线程中要完成的功能就放在run()方法中);

    3)启动线程

    a.创建线程类对象

    b.调用对象的start()方法

    示例代码:同上

    2.  使用线程时的注意事项:

    (1)  一个线程类可以创建多个线程对象,每个线程对象都可以单独启动;

    (2)  一个线程对象只能启动一次(即调用一次start()方法);

    (3)  在线程类中,重写的时run() 方法,但是在测试了中启动线程调用的是start() 方法。

    3.  Thread类中的常用方法

    1public String getName()   获取线程名称

           注:每个线程都有一个默认的线程名称:Thread—索引值

    2public  void  setName ()          设置线程名称

    3public  static  currentThread ()    获取当前线程对象

    4public  static  sleep()              使线程休眠指定的毫秒数

    示例代码:

    线程类:

    public class MyThread extends Thread{

        public void run(){

            for (int i = 0; i < 100; i++) {

                System.out.println(this.getName()+"  i="+i);

                try {

                    Thread.sleep(1000);//休眠指定的毫秒数

                } catch (InterruptedException e) {

                    e.printStackTrace();

                }

            }

        }

    }

           测试类:

    public class Demo01 {

        public static void main(String [] args){

            //创建子类对象

            MyThread myThread=new MyThread();

            myThread.setName("独立线程");//设置线程名称

            Thread.currentThread().setName("主线程");//设置线程名称

            //调用父类的start方法,启动多线程

            myThread.start();

            for (int k = 0; k < 100; k++) {

                System.out.println(Thread.currentThread().getName()+"  k="+k);//获取当前线程对象

                try {

                    Thread.sleep(1000);//休眠指定的毫秒数

                } catch (InterruptedException e) {

                    e.printStackTrace();

                }

            }

        }

    }

    三.  创建线程的方式二:实现Runnable接口

    1.  步骤

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

    (2)  重写run() 方法;

    (3)  启动线程

    a.  创建一个自定义对象

    b.  创建一个Thread对象,并将自定义对象作为参数传给Runnable的构造方法;

    c.  调用方Thread对象的start()方法启动线程。

     

     

    线程类:

    public class MyRunnable implements Runnable {

        @Override

        //重写Runnable中的run() 方法

        public void run() {

            for (int i = 0; i < 100; i++) {

                System.out.println(Thread.currentThread().getName()+"   i="+i);

                //休眠指定的毫秒数

                try {

                    Thread.sleep(1);

                } catch (InterruptedException e) {

                    e.printStackTrace();

                }

            }

        }

    }

     

    测试类:

    public class Demo {

        public static void main(String[] args) {

            //创建自定义类对象

            MyRunnable myRunnable=new MyRunnable();

            //创建Thread对象,并将自定义对象作为参数传给Thread的构造方法

            Thread thread=new Thread(myRunnable);//调用Thread对象的start()方法启动线程

            //为线程设置名称

            thread.setName("独立线程");

            Thread.currentThread().setName("主线程");

            thread.start();

            for (int k = 0; k < 100; k++) {

                System.out.println(Thread.currentThread().getName()+"   k="+k);

                //休眠指定的毫秒数

                try {

                    Thread.sleep(1);

                } catch (InterruptedException e) {

                    e.printStackTrace();

                }

            }

        }

    }

     

    四.  两种创建线程的区别

    1.  Thread 通过继承方式实现多线程,这就限制了子类的继承关系;

    2.  Runnable 通过实现接口的方式实现多线程,不会对实现类造成限制,较为灵活。

    五.  匿名内部类的方式实现线程

    1.  使用Thread匿名子类

    public class ThreadDemo {

        public static void main(String[] args) {

            new Thread(){

                public void run(){

                    for (int i = 0; i < 100; i++) {

                        System.out.println("i="+i);

                    }

                }

            }.start();

            for (int k = 0; k < 100; k++) {

                System.out.println("k="+k);

            }

        }

    }

    2.  使用Runnable

    public class RunnableDemo {

        public static void main(String[] args) {

            new Thread(new Runnable() {

                @Override

                public void run() {

                    for (int i = 0; i < 100; i++) {

                        System.out.println("i=" + i);

                    }

                }

            }).start();

            for (int k = 0; k < 100; k++) {

                System.out.println("k="+k);

            }

        }

    }

    六.  多线程的安全问题

    1.  不安全的火车票售票机制

    线程类:

    public class Tickets implements Runnable  {

        private int tickets=100;

        @Override

        public void run() {

           while(true){

               try {

                   Thread.sleep(1);

               } catch (InterruptedException e) {

                   e.printStackTrace();

               }

               if(tickets>0){

                   System.out.println("给线程"+Thread.currentThread().getName()+"取走一张票"+tickets);

                   tickets--;

               }else{

                   System.out.println("没票了...");

                   break;

               }

           }

        }

    }

     

    测试类:

    public class Demo {

        public static void main(String[] args) {

            //创建线程类对象

            Tickets tickets=new Tickets();//休眠一毫秒,可以更加明显

            //创建Thread对象,将Runnable对象作为参数传给Thread的构造方法,通过Thread对象调用方法

            Thread t1=new Thread(tickets);

            Thread t2=new Thread(tickets);

            Thread t3=new Thread(tickets);

            //设置线程名称

            t1.setName("窗口1");

            t2.setName("窗口2");

            t3.setName("窗口3");

            //启动线程

            t1.start();

            t2.start();

            t3.start();

        }

    }

    此时会出现一张票被多个人买走的情况,非常的不安全。

    七.  线程同步解决线程安全问题

    1.  使用同步代码块解决多线程安全问题

    public class Tickets implements Runnable  {

        private int tickets=100;

        Object obj=new Object();

        @Override

        public void run() {

           while(true) {

               try {

                   Thread.sleep(1);

               } catch (InterruptedException e) {

                   e.printStackTrace();

               }

               synchronized (obj) {

                   if (tickets > 0) {

                       System.out.println("给线程" + Thread.currentThread().getName() + "取走一张票" + tickets);

                       tickets--;

                   } else {

                       System.out.println("没票了...");

                       break;

                   }

               }

           }

        }

    }

    //测试类同上

     

    2.  使用同步方法解决多线程安全问题

    public class Tickets implements Runnable {

        //Object obj=new Object();

        int tickets=100;

        @Override

        public void run() {

            while(true){

                getTickets();

                try {

                    Thread.sleep(2);

                } catch (InterruptedException e) {

                    e.printStackTrace();

                }

            }

        }

        public synchronized  void getTickets() {

           if(tickets>0){

               System.out.println("线程"+Thread.currentThread().getName()+"取走了一张票"+tickets);

               tickets--;

           }else {

               System.out.println("没票了....");

               System.exit(0);

           }

        }

    }

     

    说明:同步方法可以是普通方法,也可以是静态方法。只要这个方法被多个线程同时访问,但是程序值希望只有一个线程执行全部方法体后,才允许其他线程访问,这种情况下可以将方法声明为同步方法,这样可以保证数据的安全性。

    https://www.cnblogs.com/LLLaoJia/

  • 相关阅读:
    2016/11/2
    2016/11/1
    bzoj 3809: Gty的二逼妹子序列
    bzoj 1207: [HNOI2004]打鼹鼠
    bzoj 1191: [HNOI2006]超级英雄Hero
    BZOJ 1854: [Scoi2010]游戏
    BZOJ 1296: [SCOI2009]粉刷匠
    BZOJ 1787: [Ahoi2008]Meet 紧急集合
    tarjan算法
    高级的暴力(一)——分块
  • 原文地址:https://www.cnblogs.com/LLLaoJia/p/9502892.html
Copyright © 2011-2022 走看看