首页 > 编程 > Java > 正文

JAVA 线程总结

2019-11-08 03:04:16
字体:
来源:转载
供稿:网友
线程:同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换开销小。线程和进程一样分为五个阶段:创建、就绪、运行、阻塞、终止。多线程是指在同一程序中有多个顺序流在执行。在java中创建线程有两种方法:使用Thread类和使用Runnable接口。方法一:继承Thread类覆盖run方法  (不推荐)public class ThreadDemo1 {     public static void main(String[] args){         Demo d = new Demo();         d.start();         for(int i=0;i<60;i++){             System.out.PRintln(Thread.currentThread().getName()+i);//获取当前运行线程的名字         }     } } class Demo extends Thread{     public void run(){         for(int i=0;i<60;i++){             System.out.println(Thread.currentThread().getName()+i);         }     } }方法二:(推荐)public class ThreadDemo2 {    public static void main(String[] args){        Demo2 d =new Demo2();        Thread t = new Thread(d);//为了使线程能够执行run()方法,需要在Thread类的构造函数中传入 d 的实例对象。        t.start();        for(int x=0;x<60;x++){            System.out.println(Thread.currentThread().getName()+x);        }    }}class Demo2 implements Runnable{    public void run(){        for(int x=0;x<60;x++){            System.out.println(Thread.currentThread().getName()+x);        }    }}线程在建立后并不马上执行run方法中的代码,而是处于等待状态。线程处于等待状态时,可以通过Thread类的方法来设置线程各种属性,如线程的优先级(setPriority)、线程名(setName)和线程的类型(setDaemon)等。当调用start方法后,线程开始执行run方法中的代码。线程进入运行状态。使用synchronized解决线程安全问题,共享数据问题。对Running状态的线程加同步锁(Synchronized)使其进入(lock blocked pool ),同步锁被释放进入可运行状态(Runnable)。synchronized是Java中的关键字,是一种同步锁。它修饰的对象有以下几种:1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象;2. 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;3. 修改一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;4. 修改一个类,其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象。synchronized同步代码块:public class ThreadDemo3 {    public static void main(String[] args){        Ticket t =new Ticket();        Thread t1 = new Thread(t,"窗口一");        Thread t2 = new Thread(t,"窗口二");        Thread t3 = new Thread(t,"窗口三");        Thread t4 = new Thread(t,"窗口四");        t1.start();        t2.start();        t3.start();        t4.start();    }}class Ticket implements Runnable{    private int ticket =400;    public void run(){        while(true){            synchronized (new Object()) {                try {                    Thread.sleep(1);                } catch (InterruptedException e) {                    // TODO Auto-generated catch block                    e.printStackTrace();                }                if(ticket<=0)                    break;                System.out.println(Thread.currentThread().getName()+"---卖出"+ticket--);            }        }    }}synchronized同步函数public class ThreadDemo3 {    public static void main(String[] args){        Ticket t =new Ticket();        Thread t1 = new Thread(t,"窗口一");        Thread t2 = new Thread(t,"窗口二");        Thread t3 = new Thread(t,"窗口三");        Thread t4 = new Thread(t,"窗口四");        t1.start();        t2.start();        t3.start();        t4.start();    }}class Ticket implements Runnable{    private int ticket = 4000;    public synchronized void  saleTicket(){        if(ticket>0)            System.out.println(Thread.currentThread().getName()+"卖出了"+ticket--);    }    public void run(){        while(true){            saleTicket();        }    }}synchronized, wait, notify结合:典型场景生产者消费者问题/**   * 生产者生产出来的产品交给店员   */  public synchronized void produce()  {      if(this.product >= MAX_PRODUCT)      {          try          {              wait();                System.out.println("产品已满,请稍候再生产");          }          catch(InterruptedException e)          {              e.printStackTrace();          }          return;      }      this.product++;      System.out.println("生产者生产第" + this.product + "个产品.");      notifyAll();   //通知等待区的消费者可以取出产品了  }  /**   * 消费者从店员取产品   */  public synchronized void consume()  {      if(this.product <= MIN_PRODUCT)      {          try           {              wait();               System.out.println("缺货,稍候再取");          }           catch (InterruptedException e)           {              e.printStackTrace();          }          return;      }      System.out.println("消费者取走了第" + this.product + "个产品.");      this.product--;      notifyAll();   //通知等待去的生产者可以生产产品了  }Callable和Future,一个产生结果,一个拿到结果。 Future可以拿到异步执行任务的返回值future模式:并发模式的一种,可以有两种形式,即无阻塞和阻塞,分别是isDone和get。Future future = e.submit(new myCallable());future.isDone() //return true,false 无阻塞future.get() // return 返回值,阻塞直到该线程运行结束使用Callable和Future接口创建线程。具体是创建Callable接口的实现类,并实现clall()方法。并使用FutureTask类来包装Callable实现类的对象,且以此FutureTask对象作为Thread对象的target来创建线程。import java.util.concurrent.Callable;import java.util.concurrent.ExecutionException;import java.util.concurrent.FutureTask;public class ThreadTest {    public static void main(String[] args) {        Callable<Integer> myCallable = new MyCallable();    // 创建MyCallable对象        FutureTask<Integer> ft = new FutureTask<Integer>(myCallable); //使用FutureTask来包装MyCallable对象        for (int i = 0; i < 100; i++) {            System.out.println(Thread.currentThread().getName() + " " + i);            if (i == 30) {                Thread thread = new Thread(ft);   //FutureTask对象作为Thread对象的target创建新的线程                thread.start();                      //线程进入到就绪状态            }        }        System.out.println("主线程for循环执行完毕..");                try {            int sum = ft.get();            //取得新创建的新线程中的call()方法返回的结果            System.out.println("sum = " + sum);        } catch (InterruptedException e) {            e.printStackTrace();        } catch (ExecutionException e) {            e.printStackTrace();        }    }}class MyCallable implements Callable<Integer> {    private int i = 0;    // 与run()方法不同的是,call()方法具有返回值    @Override    public Integer call() {        int sum = 0;        for (; i < 100; i++) {            System.out.println(Thread.currentThread().getName() + " " + i);            sum += i;        }        return sum;    }}并行与并发:    并行:多个cpu实例或者多台机器同时执行一段处理逻辑,是真正的同时。    并发:通过cpu调度算法,让用户看上去同时执行,实际上从cpu操作层面不是真正的同时。并发往往在场景中有公用的资源,那么针对这个公用的资源往往产生瓶颈,我们会用TPS或者QPS来反应这个系统的处理能力。线程安全与不安全:线程安全:指在并发的情况之下,该代码经过多线程使用,线程的调度顺序不影响任何结果。线程不安全:意味着线程的调度顺序会影响最终结果。阻塞的情况分三种:(一)、等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。(二)、同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。(三)、其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。线程让步:Thread.yield() 方法,暂停当前正在执行的线程对象,把执行机会让给相同或者更高优先级的线程。 线程加入:join()方法,等待其他线程终止。在当前线程中调用另一个线程的join()方法,则当前线程转入阻塞状态,直到另一个进程运行结束,当前线程再由阻

塞转为就绪状态。

【原创】原创文章,更多关注敬请关注微信公众号。


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表