并发编程[一]

一、什么是线程

  个人理解:线程就是轻量的进程,产生在进程里面,一个进程可以有多个线程。

二、线程的基本操作

  1、新建状态(new): 当用new操作符创建一个线程时, 例如new Thread(r),线程还没有开始运行,此时线程处在新建状态。 当一个线程处于新生状态时,程序还没有开始运行线程中的代码。

Thread thread = new Thread();

   2、就绪状态(Runnable):一个新创建的线程并不自动开始运行,要执行线程,必须调用线程的start()方法。当线程对象调用start()方法即启动了线程,start()方法创建线程运行的系统资源,并调度线程运行run()方法。当start()方法返回后,线程就处于就绪状态。

    Thread thread = new Thread() {
			@Override
			public void run() {
				try {
					System.out.println("thread 3 running....");
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} finally {
					System.out.println("thread 3 stoped....");
				}
			}
		};    

 

   3、运行状态(Running): 当线程获得CPU时间后,它才进入运行状态,真正开始执行run()方法。注意:调用run()方法并不是启动一个线程,只是调用了一个方法  

Thread thread = new Thread();
thread.start();

   4、阻塞状态(Blocked):所谓阻塞状态是正在运行的线程没有运行结束,暂时让出CPU,这时其他处于就绪状态的线程就可以获得CPU时间,进入运行状态。         

thread.sleep();
thread.wait();

   上面两种方法都能让线程处于阻塞状态,区别在于sleep()不会释放锁,wait()会释放锁;sleep是Thread方法,wait()是Object方法

  5、死亡状态(Dead):正常执行完run方法和执行run方法异常都会使线程死亡;为了确定线程在当前是否存活着(就是要么是可运行的,要么是被阻塞了),需要使用isAlive方法。如果是可运行或被阻塞,这个方法返回true; 如果线程仍旧是new状态且不是可运行的, 或者线程死亡了,则返回false

  6、终止线程

Thread.stop();//不推荐使用。它会释放所有monitor 会出现消息不一致情况

   7、中断线程

public void Thread.interrupt() // 中断线程
public boolean Thread.isInterrupted() // 判断是否被中断
public static boolean Thread.interrupted() // 判断是否被中断,并清除当前中断状态

   8、挂起(suspend)和继续执行(resume)线程

    suspend()不会释放锁
    – 如果加锁发生在resume()之前 ,则死锁发生

  9、等待线程结束(join)和谦让(yeild)

  join()方法

package com.cc.thread;

import org.junit.Test;

public class ThreadTest01 {

    /**
     * 现在有T1、T2、T3三个线程,你怎样保证T2在T1执行完后执行,T3在T2执行完后执行?
     * Java Thread中, join() 方法是让调用该方法的主线程执行run()时暂时卡住,等run()执行完成后, 主线程再调用执行join()后面的代码
     * 如果去掉t1.join()这个语句过后, 输出的顺序是乱的, 加上这个语句后, 就会按照顺序输出,  从某种意义上说实现了同步。
     */
    @Test
    public void Test1(){
        //线程1
        Thread thread1 = new Thread() {
            @Override
            public void run() {
                try {
                    System.out.println("thread 1 running....");
                    //sleep(1000);
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } finally {
                    System.out.println("thread 1 stoped....");
                }
                super.run();
            }
        };
        //线程2
        Thread thread2 = new Thread() {
            @Override
            public void run() {
                try {
                    System.out.println("thread 2 running....");
                    //sleep(1000);
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } finally {
                    System.out.println("thread 2 stoped....");
                }
                super.run();
            }
        };
        //线程3
        Thread thread3 = new Thread() {
            @Override
            public void run() {
                try {
                    System.out.println("thread 3 running....");
                    //sleep(1000);
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } finally {
                    System.out.println("thread 3 stoped....");
                }
                super.run();
            }
        };
        try {
            thread1.start();
            thread1.join();
            thread2.start();
            thread2.join();
            thread3.start();
            thread3.join();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

  yield()方法

package com.cc.demo01;
/**
 * yield()谦让
 * 使当前线程从执行状态(运行状态)变为可执行态(就绪状态)。cpu会从众多的可执行态里选择,也就是说,
 * 当前也就是刚刚的那个线程还是有可能会被再次执行到的,并不是说一定会执行其他线程而该线程在下一次中不会执行到了。
 * @author chao
 *
 */
public class ThreadDemo02 extends Thread {
	public ThreadDemo02(String name) {
		super(name);
	}

	public void run() {
		for (int i = 1; i <= 30; i++) {
			System.out.println("" + this.getName() + "-----" + i);
			// 当i为10时,该线程就会把CPU时间让掉,让其他或者自己的线程执行(也就是谁先抢到谁执行)
			if (i == 10) {
				this.yield();
			}
		}
	}

	public static void main(String[] args) {
		ThreadDemo02 t1 = new ThreadDemo02("张三");
		ThreadDemo02 t2 = new ThreadDemo02("李四");
		t1.start();
		t2.start();
	}
}

   10、守护线程

    在后台默默地完成一些系统性的服务,比如垃圾回收线程、 JIT线程就可以理解为守护线程

    当一个Java应用内,只有守护线程时,Java虚拟机就会自然退出

    Thread t=new DaemonT();
    t.setDaemon(true);
    t.start();

  11、线程优先级

    public final static int MIN_PRIORITY = 1;
    public final static int NORM_PRIORITY = 5;
    public final static int MAX_PRIORITY = 10;

package com.cc.demo01;
/**
 * yield()谦让
 * 使当前线程从执行状态(运行状态)变为可执行态(就绪状态)。cpu会从众多的可执行态里选择,也就是说,
 * 当前也就是刚刚的那个线程还是有可能会被再次执行到的,并不是说一定会执行其他线程而该线程在下一次中不会执行到了。
 * @author chao
 *
 */
public class ThreadDemo02 extends Thread {
	public ThreadDemo02(String name) {
		super(name);
	}

	public void run() {
		for (int i = 1; i <= 30; i++) {
			System.out.println("" + this.getName() + "-----" + i);
			// 当i为10时,该线程就会把CPU时间让掉,让其他或者自己的线程执行(也就是谁先抢到谁执行)
			if (i == 10) {
				this.yield();
			}
		}
	}

	public static void main(String[] args) {
		ThreadDemo02 t1 = new ThreadDemo02("张三");
		ThreadDemo02 t2 = new ThreadDemo02("李四");
		t1.start();
		//优先级高的会在下次竞争中更容易获胜
		t1.setPriority(MIN_PRIORITY);
		t2.start();
		t2.setPriority(MAX_PRIORITY);
	}
}

 三、基本的线程同步操作
  synchronized
    指定加锁对象:对给定对象加锁,进入同步代码前要获得给定对象的锁。
    – 直接作用于实例方法:相当于对当前实例加锁,进入同步代码前要获得当前实例的锁。
    – 直接作用于静态方法:相当于对当前类加锁,进入同步代码前要获得当前类的锁。
  Object.wait() Obejct.notify();

package com.cc.thread;


public class ThreadTest02{
	public static final Object obj = new Object();
	public static void main(String[] args) {
		new Thread(new Producer()).start();
		new Thread(new Consumer()).start();
	}
}

/**
 * 两个线程依次打印"A""B",总共打印10次。
 * 
 * @author chao 这里使用static
 *         obj作为锁的对象,当线程Produce启动时(假如Produce首先获得锁,则Consumer会等待),打印
 *         “A”后,会先主动释放锁,然后阻塞自己
 *         。Consumer获得对象锁,打印“B”,然后释放锁,阻塞自己,那么Produce又会获得锁,然后...一直循环下去,直到count =
 *         0.这样,使用Synchronized和wait()以及notify()就可以达到线程同步的目的。
 * 
 */
class Consumer implements Runnable{
	@Override
	public void run() {
		int count = 10;
		while(count>0){
			synchronized (ThreadTest02.obj) {
				//wait()和notify()必须在synchronized代码块中调用
				System.out.println("B");
				count --;
				ThreadTest02.obj.notify(); // 主动释放对象锁
				 try {
					 ThreadTest02.obj.wait();//阻塞当前对象
               } catch (InterruptedException e) {
                      // TODO Auto-generated catch block
                     e.printStackTrace();
               }
			}
		}
	}
	
}
class Producer implements Runnable{

	@Override
	public void run() {
		int count = 10;
		while(count>0){
			synchronized (ThreadTest02.obj) {
				System. out.println( "A");
                count --;
                ThreadTest02.obj.notify();//主动释放当前对象锁
                 try {
                	 ThreadTest02.obj.wait();//阻塞当前对象
                } catch (InterruptedException e) {
                       // TODO Auto-generated catch block
                      e.printStackTrace();
                }
			}
		}
		
	}
	
}

 

  

 

posted @ 2017-12-26 16:11  骑着小毛驴  阅读(132)  评论(0编辑  收藏  举报