多线程

1,初识Java多线程

      (1)线程简介

        进程:是一个正在执行中的程序。每一个进程执行都有一个执行顺序,该顺序是一个执行路径,或者叫一个控制单元。

        线程:就是进程中的一个独立的控制单元。线程在控制着进程的执行。一个进程可以包含一个或多个线程。

      (2)线程的四种状态

      (3)自定义线程

        自定义线程有两种方式:一种是继承Thread类,另一种是实现Runnable接口。

        a,通过继承Thread类实现自定义线程步骤:定义类继承Thread;复写Thread类中的run方法;调用线程的start方法。

运行示例:

class Demo extends Thread{
 int count = 0;
 public void run(){
  while(count<20){
   count++;
   System.out.println(currentThread().getName()+"\t"+count);
  }
 }
}
public class ThreadDemo {
 public static void main(String[] args) {
  Demo d1 = new Demo();
  Demo d2 = new Demo();
  System.out.println("Thread1 start!");
  d1.start();
  System.out.println("Thread2 start!");
  d2.start();
  System.out.println("OK!!!");
 }
}

        b,通过实现Runnable接口实现自定义线程步骤:定义类实现Runnable接口;覆盖Runnable接口中的run方法;通过Thread类建立线程对象;将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数。

运行示例:

class Demo implements Runnable{
 int count = 0;
 public void run(){
  while(count<20){
   count++;
   System.out.println(currentThread().getName()+"\t"+count);
  }
 }
}
public class ThreadDemo {
 public static void main(String[] args) {
  Demo d = new Demo();
  Thread t1 = new Thread(d);
  Thread t2 = new Thread(d);
  System.out.println("Thread1 start!");
  d1.start();
  System.out.println("Thread2 start!");
  d2.start();
  System.out.println("OK!!!");
  }
}

2,线程同步

      (1)同步的应用

        多线程程序中,由于同时有多个线程并发执行,有时会带来严重的问题,甚至引发错误。因此,必须采用同步机制来防止类似情况的发生,即在一个线程完成操作之前,禁止其他对象访问该对象。

        Java提供了同步方法和同步状态来实现同步,被宣布为同步的方法、对象或类数据,在任一时刻只能被一个线程使用。

        同步方法指用synchronized修饰的方法。同步方法当一个线程执行时自动加锁,直到方法运行结束,锁解除。同步状态指用synchronized(Object)标识的语句块。语句块被一个线程执行时会自定加锁,直到运行结束,锁解除。

        同步状态也就是同步代码块。

        synchronized(对象){
               需要被同步的代码;
        }

        同步的前提:a,必须要有两个或者两个以上的线程;  b,必须是多个线程使用同一个锁。

运行示例:

public class SynchTest implements Runnable{
 public static void main(String[] args) {
  SynchTest st = new SynchTest();
  Thread t1 = new Thread(st);
  Thread t2 = new Thread(st);
  t1.start();
  t2.start();
  while((t1.isAlive())||(t2.isAlive()));
  System.out.println("The test is end.");
 }
 public void run(){
  String name = Thread.currentThread().getName();
  show(name);
  System.out.println(name+" is dead!");
 }
 private synchronized void show(String name){
  for (int i = 1; i <= 500; i++) {
   System.out.println("I am "+name+"--I have run "+i+" times.");
  }
 }
}

上述例程也可以改为用同步代码块来实现,只需把show方法改写成:

 private void show(String name){
  synchronized ("Test") {
   for (int i = 1; i <= 500; i++) {
    System.out.println("I am " + name + "--I have run " + i+ " times.");
   }
  }
 }

      (2)同步中使用的锁

        同步代码块中使用的锁是synchronized(对象){ }中的对象。

        函数需要被对象调用,那么函数都有一个所属对象引用,就是this。所以同步方法使用的锁是this。

        静态的同步方法使用的锁是该方法所在类的字节码文件对象。  类名.class

      (3)死锁

        死锁产生的原因:同步中嵌套同步。

产生死锁示例:

class Test implements Runnable{//产生死锁示例
 private boolean flag;
 Test(boolean flag){
  this.flag = flag;
 }
 public void run(){
  if(flag){
   synchronized(MyLock.locka){
    System.out.println("if locka");
    synchronized(MyLock.lockb){
     System.out.println("if lockb");
    }
   }
  }
  else{
   synchronized(MyLock.lockb){
    System.out.println("else lockb");
    synchronized(MyLock.locka){
     System.out.println("else locka");
    }
   }
  }
 }
}
class MyLock{
 public static Object locka = new Object();
 public static Object lockb = new Object();
}
public class BankDemo {
 public static void main(String[] args) {
  Thread t1 = new Thread(new Test(true));
  Thread t2 = new Thread(new Test(false));
  t1.start();
  t2.start();
 }
}

3,线程中基本方法

      (1)start

        public void start():使该线程开始执行;Java 虚拟机调用该线程的run方法。结果是两个线程并发地运行;当前线程(从调用返回给start方法)和另一个线程(执行其run方法)。多次启动一个线程是非法的。特别是当线程已经结束执行后,不能再重新启动。

      (2)run

        public void run():如果该线程是使用独立的Runnable运行对象构造的,则调用该Runnable对象的run方法;否则,该方法不执行任何操作并返回。Thread 的子类应该重写该方法。

      (3)sleep

        public static void sleep(long millis)throwsInterruptedException:在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。该线程不丢失任何监视器的所属权。

        public static void sleep(long millis,int nanos)throwsInterruptedException:在指定的毫秒数加指定的纳秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。该线程不丢失任何监视器的所属权。

      (4)currentThread

        public static Thread currentThread():返回对当前正在执行的线程对象的引用。

      (5)yield

        public static void yield():暂停当前正在执行的线程对象,并执行其他线程。

      (6)getName

        public final String getName():返回该线程的名称。

      (7)interrupt

        public void interrupt():结束线程的冻结状态,使线程回到运行状态中来。如果线程在调用 Object 类的 wait()wait(long)wait(long, int) 方法,或者该类的join()join(long)join(long, int)sleep(long)sleep(long, int) 方法过程中受阻,则其中断状态将被清除,它还将收到一个InterruptedException

      (8)join

        public final void join() throws InterruptedException:等待该线程终止。

      (9)setDaemon

        public final void setDaemon(boolean on):将该线程标记为守护线程或用户线程。当正在运行的线程都是守护线程时,Java 虚拟机退出。该方法必须在启动线程前调用。

        注意:了解更多用法,请下载JDK API 1.6.0中文版。

4,从类Object继承的方法

        notify,notifyAll,wait:都使用在同步中,因为要对持有监视器(锁)的线程操作。所以要使用在同步中,因为只有同步才具有锁。

5,Lock替换Synchronized

        JDK1.5中提供了多线程升级解放方案。将同步Synchronized替换成Lock操作。将Object中的wait,notify,notifyAll替换成Condition对象中await,signal,signalAll。

运行示例:

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class Resource1{//仓库
 private String name;
 private int count = 1;
 private boolean flag = false;
 final Lock lock = new ReentrantLock();
 final Condition condition_pro = lock.newCondition();
 final Condition condition_con = lock.newCondition();
 public void set(String name) throws InterruptedException {
  lock.lock();
  try {
   while (flag)
    condition_pro.await();
   this.name = name + "---" + count++;
   System.out.println(Thread.currentThread().getName() + "...生产者..." + this.name);
   flag = true;
   condition_con.signal();
  } finally {
   lock.unlock();//释放锁的动作一定要执行
  }
 }

 public void out() throws InterruptedException {
  lock.lock();
  try {
   while (!flag)
    condition_con.await();
   System.out.println(Thread.currentThread().getName() + "...消费者..." + this.name);
   flag = false;
   condition_pro.signal();
  } finally {
   lock.unlock();
  }
 }
}
class Producer1 implements Runnable{//生产者
 private Resource1 res;
 Producer1(Resource1 res){
  this.res = res;
 }
 public void run(){
  while(true){
   try {
    res.set("+商品+");
   } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  }
 }
}
class Consumer1 implements Runnable{//消费者
 private Resource1 res;
 Consumer1(Resource1 res){
  this.res = res;
 }
 public void run(){
  while(true){
   try {
    res.out();
   } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  }
 }
}
public class ProducerConsumerDemo1 {
 public static void main(String[] args) {
  Resource1 r = new Resource1();
  Producer1 pro = new Producer1(r);
  Consumer1 con = new Consumer1(r);
  Thread t1 = new Thread(pro);
  Thread t2 = new Thread(pro);
  Thread t3 = new Thread(con);
  Thread t4 = new Thread(con);
  t1.start();
  t2.start();
  t3.start();
  t4.start();
 }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值