多线程编程

一、什么是进程,什么是线程

打开系统监视器,我们就可以查看正在运行的进程有哪些。例如:

以firefox为例,它是一个浏览器应用程序,当它开始运行的时候就成为一个进程(它为程序创建执行环境)。而firefox这个进程独自占有一些系统资源(例如CPU)和Memory(本例中当前状态是104.0KiB)。

Thread是进程中的单一的执行流,一个进程中可以存在多个线程,这些线程共享这个进程的拥有的系统资源。每个Java程序的main函数都是一条顺序执行流,下面是最简单的Java程序:

package org.vhow.java.thread;

public class AppMain
{
	public static void main(String[] args)
	{
	}
}
我们来调试它:

可以看到,这个程序当前正在执行的Thread名为main。

二、为什么使用线程

1。 资源共享。

同一父进程的线程间共享这个进程所申请的系统资源。而不像进程那样各自占有一些系统资源。不过,线程可以拥有自己的栈空间、自己的程序计数器和自己的局部变量。

2。 并发执行。

线程是独立的执行流,每个线程都可以独立执行自己的顺序流,而不用等待其它线程。

三、线程的创建和启动

在我们使用迅雷下载文件的时候,可以同时下载多个文件。每个文件的下载都是一个顺序执行流,都是线程。这些线程并发执行。现在,我们用程序来模拟这个场景.

package org.vhow.java.thread;

public class AppMain
{
	public static void main(String[] args)
	{
		DownLoader downloader = new DownLoader();
		
		Thread movie = new Thread(downloader);
		movie.setName("movie");
		movie.start();
		
		Thread music = new Thread(downloader);
		music.setName("music");
		music.start();
		
		Thread text = new Thread(downloader);
		text.setName("text file");
		text.start();
		
		System.out.println();
	}
}

class DownLoader implements Runnable
{
	@Override
	public void run()
	{
		while (true)
		{
			System.out.println("downloading " + Thread.currentThread().getName());
			try
			{
				Thread.sleep(1000);
			}
			catch (InterruptedException e)
			{
				e.printStackTrace();
			}
		}
	}
}

在每个start()语句处设置断电,调试这个程序,我们会发现在执行打印空行的语句前,程序中同时存在四个线程:

除了像以上一样创建一个Runnable对象,我们还可以创建一个Thread类的扩展类来定义一个线程。例如:

package org.vhow.java.thread;

class DownThread extends Thread
{
	@Override
	public void run()
	{
		// do something in this thread
	}
}

public class AppMain
{
	public static void main(String[] args)
	{
		new DownThread().start();
	}
}

四、线程同步

当多个线程同时访问同一个对象的数据时,可能会出现问题,例如下面的程序,ThreadA和ThreadB同时操作同一个值,一个对其加1,一个对其减1,可结果却不是原来的值:

package org.vhow.java.thread;

class Counter
{
 private int value = 0;

 public void increment()
 {
  int temp = this.getValue();
  System.out.println(Thread.currentThread().getName()
    + " read the value is " + temp);
  temp++;
  try
  {
   Thread.sleep(100);
  }
  catch (InterruptedException e)
  {
   e.printStackTrace();
  }
  System.out.println(Thread.currentThread().getName()
    + " increment the value by 1 ");
  value = temp;
 }

 public void decrement()
 {
  int temp = this.getValue();
  System.out.println(Thread.currentThread().getName()
    + " read the value is " + temp);
  try
  {
   Thread.sleep(200);
  }
  catch (InterruptedException e)
  {
   e.printStackTrace();
  }
  System.out.println(Thread.currentThread().getName()
    + " think the vlaue is " + temp + " but it is "
    + this.getValue() + " now.");
  System.out.println(Thread.currentThread().getName()
    + " decrement the value by 1 ");
  temp--;
  value = temp;
 }

 public int getValue()
 {
  return value;
 }
}

class ThreadA extends Thread
{
 Counter counter = new Counter();

 public ThreadA(Counter counter)
 {
  this.counter = counter;
 }

 @Override
 public void run()
 {
  counter.increment();
 }
}

class ThreadB extends Thread
{
 Counter counter = new Counter();

 public ThreadB(Counter counter)
 {
  this.counter = counter;
 }

 @Override
 public void run()
 {
  counter.decrement();
 }
}

public class AppMain
{
 public static void main(String[] args) throws InterruptedException
 {
  Counter counter = new Counter();

  ThreadA threadA = new ThreadA(counter);
  threadA.setName("Thread-A");
  threadA.start();

  ThreadB threadB = new ThreadB(counter);
  threadB.setName("Thread-B");
  threadB.start();

  threadA.join();
  threadB.join();
  System.out.println("The result is " + counter.getValue());
 }
}

我们假设操作系统和程序本身都未添加多线程处理,这种情况就像是你和另一个人同时打开了服务器上的一个Excel文件并都做了一些修改,你先保存,那个人再并保存。这样,你修改的内容就消失了。那么我们怎么避免这样的事情发生呢。有两个办法:

1。 正和实际情况一下,如果已经有一个人打开了这个文档(正在编辑),在直到这个人完成编辑前,Excel就会阻止第二个人再次打开它。

2。 你先编辑,另一个人等待。在你完成编辑并保存后,通知另一个人。

对应的代码处理方法如下:

1.1 使用synchronized关键字同步方法。

	public synchronized void increment()
	{
		value++;
	}

	public synchronized void decrement()
	{
		value--;
	}
当已经有一个线程正在执行某个对象synchronized的方法时,其它想要执行同一个对象的synchronized的方法时,必须等待。

1.2 使用synchronized同步对象

	public void increment()
	{
		synchronized (this)
		{
			value++;
		}
	}

	public void decrement()
	{
		synchronized (this)
		{
			value--;
		}
	}
概念与上一个方法类似,当一个线程获得某个实例对象的锁并且没有释放之前,其它试图获得这个对象的锁的线程只能等待。

未完,待续。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值