JAVASE_多线程

来源:互联网 发布:年度数据分析报告 编辑:程序博客网 时间:2024/04/19 23:38
java中产生线程的方式有两种,第一种是:继承Thread类,并覆盖其run方法第二种是:实现Runnable接口中的run方法*注意:run中实现的代码,就是多线程要执行的代码Resource r = new Resource();Thread t1 = new Thread(r);Thread t2 = new Thread(r);t1.start();//启动两个线程ts.start();//这两个线程共用Resource对象中的变量//线程共享变量一般采用volatile修饰符来修饰多线程:1.进程是一个正在执行中的程序。2.每一个进程的执行都有一个执行的顺序,该顺序是一个执行路径。3.每一个进程的创建都会获得内存空间,标识空间,进程代表了一个个应用程序,而线程才是进程中的控制单元,控制着进程的执行。为什么要覆盖run方法?Thread类用于描述线程。该类定义了一个功能用于存储线程要执行的代码,该存储功能就是run方法。线程的几个状态: 1.被创建(new Thread(xx)) 2.运行(xx.start()) 3.冻结(xx.sleep(time):睡眠time时间,时间到后自动进入到运行状态。wait():线程进入等待,需要被notify()唤醒,否则永远处于等待被唤醒的状态) 4.阻塞(具备运行资格,但是没有运行权利(资源不足等)) 5.消亡:线程运行正常结束或者采用stop方法使线程结束 线程都有自己默认的名称:Thread-编号(编号从0开始)实现runnable接口的好处:可以避免单继承的局限性。能更容易的共享数据资源。线程安全问题:当多个线程共享某对象中数据时,多个线程都在执行某段代码,而该代码存在线程安全问题时,可以通过控制给该段代码加锁,某一时刻只有一个线程能执行该段代码,其他线程必须等待运行该段代码的线程结束和再执行解决方式:(同步代码块)synchronized(任何对象){...需要被同步的代码块...}需要同步代码块的条件:哪些代码块被在线程间是数据共享的。多线程问题:1.明确哪些代码是多线程共享代码2.明确共享数据3.明确多线程代码中哪些代码是共享数据的代码函数同步代码块:(写同步时最好用相同的对象,相同的锁)public synchronized void add(int n){//默认的对象锁为thissum = sum + n ;System.out.println("sum="+sum);}以上等价于:public void add(int n){synchronized(this){sum = sum + n ;System.out.println("sum="+sum);}}当一个同步代码块的方法被static修饰时:使用的锁是该方法所在类的字节码文件对象。该对象 = 类.classpublic synchronized void add(int n){//默认的对象锁是:类名.class 该对象的类型为Class(静态被加载到内存中时,内存中不会有本类对象,但是一定会有该类对应的字节码文件对象)sum = sum + n ;System.out.println("sum="+sum);}同步代码块,在单例模式中的应用:Class Single{private static Single s = null;public static Single getInstance(){if(s == null){synchronized(Single.clss){//锁为Single字节码文件对象if(s == null )s = new Single();}}return s;}}
package 多线程.火车站购票系统;public class Tick_100 {public static void main(String[] args) {/*Ticks t = new Ticks();Ticks t1 = new Ticks();Ticks t2 = new Ticks();Ticks t3 = new Ticks();t.start();// 该线程已经从就绪状态进入了开始运行状态,以下三个start就没的意义了t1.start();t2.start();t3.start();*/Ticks_1 t_1 = new Ticks_1();Thread tt = new Thread(t_1);// Thread的run方法是调用的t_1中的run方法Thread tt1 = new Thread(t_1);Thread tt2 = new Thread(t_1);Thread tt3 = new Thread(t_1);tt.start();tt1.start();tt2.start();tt3.start();}}// 创建方式一无法不利于实现线程见的数据共享class Ticks extends Thread {private static int t = 100;// 静态变量耗内存public void run() {while (true) {if (t > 0)System.out.println(Thread.currentThread().getName() + ":" + t--);elsebreak;}}}// 创建线程的方式二(实现runnable接口)class Ticks_1 implements Runnable {private int t = 100;Object obj = new Object();public void run() {while (true) {synchronized (obj) {//对象锁,用到的是对象中的状态字,synchronized中的对象可以是任意对象if (t > 0)System.out.println(Thread.currentThread().getName() + ":"+ t--);elsebreak;}}}}
多线程之间的通信:线程间采用共享同一数据块,该数据块可以封装后对象后,把该同一对象的引用传递给两个线程调用,能达到线程间通信的功能,但是这样做的会产生线程间的安全问题.等待唤醒机制:等待的线程通常放在线程池当中,而notify()通常唤醒的是线程池中的第一个等待的线程。xx.wait()和xx.notify(),xx为对象锁。唤醒对象锁对应的线程如果对象调用了wait方法就会使持有该对象的线程把该对象的控制权交出去,然后处于等待状态。如果对象调用了notify方法就会通知某个正在等待这个对象的控制权的线程可以继续运行。如果对象调用了notifyAll方法就会通知所有等待这个对象控制权的线程继续运行。停止线程:stop()方法已经过时。解决方法是:现在大多数的线程都跑在循环结构里面,只要结束循环就可以结束线程。守护线程:setDaemon(true);当程序主线程运行结束时,程序守护线程自动结束。


0 0