多线程(一)

多线程(一)

October 6, 2016 9:13 PM Power By DeiMo

多线程概述

1.进程与线程

  • 进程:正在运行中的程序
  • 线程:进程中负责程序执行的控制单元(执行路径)一个进程可以有多个执行路径,称之为多线程

2.多线程的意义

开启多个线程是为了同时运行多部分代码,每一个线程都有自己运行的内容。这个内容就是多线程要执行的任务

3.多线程的好处与弊端

  • 好处:解决了多部分程序同时运行的问题。
  • 弊端:线程太多反而会导致CPU处理效率的降低,这是因为应用程序的执行都是CPU在做着快速的切换完成的,而这个切换是随机的。(请参考CPU工作原理)

创建多线程的两种方式

1.继承Thread类并重写run()方法
使用步骤

1)继承Thread类
2)重写run()方法
3)构造Thread对象
4)调用start()方法,开启线程

class Demo extends Thread {
    private String name;

    public Demo(String name) {
        super(name);
        this.name = name;
    }

    @Override
    public void run() {
        show();
    }

    private void show() {
        for (int i = 0; i < 10; i++) {
            System.out.println(name + "...." + i+"...."+Thread.currentThread().getName());
        }
    }
}

public class ThreadDemo {
    public static void main(String[] args) {
        Demo d1 = new Demo("hahah");
        Demo d2 = new Demo("xixixixi");
        d1.start();
        d2.start();
        System.out.println("------------------------------------------------"+Thread.currentThread().getName());
    }
}
2.实现Runnable接口(封装线程任务)
使用步骤

1)实现Runnable接口
2)重写run()方法
3)构造Thread对象
4)调用start()方法,开启线程

class Ticket implements Runnable {
    private  int num = 100;

    @Override
    public void run() {
        while (true) {
            if (num > 0) {
                System.out.println(Thread.currentThread() + "....." + num--);
            }
        }
    }
}
public class ThreadTest {
    public static void main(String[] args) {

        Ticket t = new Ticket();
        Thread t1 = new Thread(t);
        Thread t2 = new Thread(t);

        t1.start();
        t2.start();
    }
}

不难发现使用第二种方式有如下好处

1.将线程的任务从子类中分离出来,进行了单独的封装。按照面向对象的思想将任务封装成对象,提供更大的灵活性
2.避免了单继承的局限性

多线程运行图解

运行图解

多线程的运行状态

运行状态

线程安全

问题的产生

当一个线程在执行操作共享数据的多条代码中,其它线程若参与了运算,就会导致线程安全问题的产生。

产生原因:
  • 1.多个线程在操作共享数据
  • 2.操作数据的代码有多条
解决方案
解决思路

将多条操作共享数据的代码封装起来,当有线程在执行这些代码时候,其他线程不可以参与运算。简单说来:就是必须要当前代码都执行完毕后,其他线程才可以参与运算。

具体方法

针对上述思路,java提供了一种称为“同步(synchronized)”解决方案,它有两种表现形式

  • 同步代码块

    //同步代码块的格式
    synchronized(Object obj){//这里的obj称为:”锁“对象,理论上可以为任意类型
        //要同步的代码块
    }
    
  • 同步函数(同步代码块的简写形式,在修饰符后,返回值前使用关键字 synchronized

    class Ticket implements Runnable {
    private  int num = 100;
    private Object obj = new Object();
    boolean flag = true;
    
    @Override
    public void run() {
        System.out.println("this:"+this);
        if (flag) {
            while (true) {
                synchronized (obj) {
                    if (num > 0) {
                        try {
                            Thread.sleep(10);
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread() + ".....obj...."
                                + num--);
                    }
                }
            }
        } else {
            while (true) {
    
                show();
            }
        }
    
    }
    
        private synchronized void show() {
            if (num > 0) {
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread() + "...this..." + num--);
            }
        }
    }
    
    public class SynFunctionLockDemo {
        public static void main(String[] args) {
            Ticket t = new Ticket();
            System.out.println("t:"+t);
            Thread t1 = new Thread(t);
            Thread t2 = new Thread(t);
            t1.start();
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            t.flag = false;
            t2.start();
        }
    }
    
同步的相关说明


  • 好处

解决了线程的安全问题

  • 弊端
    相对降低了效率,因为同步的线程都会去判断同步锁
  • 使用前提
    同步中必须有多个线程并使用同一个锁
同步中的锁
  • 锁的概念

    一段synchronized的代码被一个线程执行之前,他要先拿到执行这段代码的权限,在Java里边就是拿到某个同步对象的锁(一个对象只有一把锁); 如果这个时候同步对象的锁被其他线程拿走了,他(这个线程)就只能等了(线程阻塞在锁池等待队列中)。 取到锁后,他就开始执行同步代码(被synchronized修饰的代码);线程执行完同步代码后马上就把锁还给同步对象,其他在锁池中等待的某个线程就可以拿到锁执行同步代码了。这样就保证了同步代码在统一时刻只有一个线程在执行。

  • 同步函数的锁

    非静态同步函数的锁是 this
    静态同步函数的锁是 同步所在类Class对象,可由this.getclass()方法或者类.class属性获取

死锁

由于死锁深入研究起来比较复杂,此处仅简要说明,并附上一个java死锁的示例

死锁的概念

死锁是进程死锁的简称,是由Dijkstra于1965年研究银行家算法时首先提出来的。它是计算机操作系统乃至并发程序设计中最难处理的问题之一。实际上,死锁问题不仅在计算机系统中存在,在我们日常生活中它也广泛存在。所谓死锁,是指多个进程循环等待它方占有的资源而无限期地僵持下去的局面。很显然,如果没有外力的作用,那麽死锁涉及到的各个进程都将永远处于封锁状态。

示例代码
class Test implements Runnable {
    protected boolean flag;

    public Test(boolean flag) {
        super();
        this.flag = flag;
    }

    @Override
    public void run() {
        if (flag) {
            synchronized (Mylock.loacA) {
                System.out.println("if................lockA");
                synchronized (Mylock.lockB) {
                    System.out.println("if..................loackB");
                }
            }
        } else {
            synchronized (Mylock.lockB) {
                System.out.println("else..................loackB");
                synchronized (Mylock.loacA) {
                    System.out.println("else..................loackA");
                }
            }
        }
    }
  }

   class Mylock {
        public static final Mylock loacA = new Mylock();
        public static final Mylock lockB = new Mylock();
  }

    public class DeadLockTest {
        public static void main(String[] args) {
            Test test1 = new Test(true);
            Test test2 = new Test(false);

            Thread t1 = new Thread(test1);
            Thread t2 = new Thread(test2);
            t1.start();
            t2.start();
        }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值