`

多线程简单设计

阅读更多
线程直接的通信:通过管道流进行简单的交互
public class ThreadDemo6 {
	public static void main(String[] args) {
		PipedOutputStream pos=null;
		PipedInputStream pis=null;
		try {
			pos=new PipedOutputStream();
			pis=new PipedInputStream(pos);
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		Sender sender=new Sender(pos);
		Thread t1=new Thread(sender);
		Receiver receiver=new Receiver(pis);
		Thread t2=new Thread(receiver);
		t1.start();
		t2.start();
		
	}
}

class Sender implements Runnable {
	private OutputStream out;

	public Sender(OutputStream out) {
		super();
		this.out = out;
	}

	@Override
	public void run() {
		for (int i = 1; i <= 5; i++) {
			byte value = (byte) (Math.random() * 100);
			System.out.println("send value is " + value);
			try {
				out.write(value);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

class Receiver implements Runnable {
	private InputStream in;

	public Receiver(InputStream in) {
		super();
		this.in = in;
	}

	@Override
	public void run() {
		for (int i = 1; i <= 5; i++) {
			try {
				byte value = (byte) in.read();
				System.out.println("receiver value is " + value);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

有一个弊端就是在所有的数据写完后才能去读取,这样在写的时候一直占用内存,我们希望每写一点就能拿一点。看下边的实现:

线程直接的通信:使用Thread.yield()模拟一个生产者和消费者的模型
* 效率还是比较差。yield方法是主动放弃了cpu,又去竞争。
public class ThreadDemo7 {
	public static void main(String[] args) {
		FlagSend flagSend = new FlagSend();
		FlagRec flagRec = new FlagRec(flagSend);
		Thread t1 = new Thread(flagSend);
		Thread t2 = new Thread(flagRec);
		t1.start();
		t2.start();

	}
}

class FlagSend implements Runnable {
	int theValue;
	boolean flag;//是否有食物:true有食物

	@Override
	public void run() {
		for (int i = 1; i <= 5; i++) {
			while (flag) {
				Thread.yield();
			}
			theValue = new Random().nextInt(1000);// 制造食物
			System.out.println("send value is " + theValue);
			flag = true;// 等待食客去吃
		}
	}
}

class FlagRec implements Runnable {

	public FlagRec(FlagSend flagSend) {
		super();
		this.flagSend = flagSend;
	}
	private FlagSend flagSend;

	@Override
	public void run() {
		for (int i = 1; i <= 5; i++) {
			while (!flagSend.flag) {
				Thread.yield();
			}
			System.out.println("receiver value is " + flagSend.theValue);
			flagSend.flag = false;
		}
	}

}

yield方法是主动放弃了cpu,又去竞争。效率比较差,接收的人不知道是否send已经Ok了。我们希望我们发送以后就去提醒接收者去拿不是一直去在放弃。

线程直接的通信:wait/notify 任何一个对象都拥有一个线程等待池
* 挂在同一个对象的线程等待池中的线程之间可以互相唤醒 wait/notify是属于Object类的
* wait方法必须放入synchronized同步块中

/**
 * @author Janle
 *
 */
public class ThreadDemo8 {
	public static void main(String[] args) {
		Cooker cooker=new Cooker();
		Diners diners=new Diners(cooker);
		Thread t1=new Thread(cooker);
		Thread t2=new Thread(diners);
		//当程序只有守护线程时候程序退出。
		t2.setDaemon(true);
		t1.start();
		t2.start();
		
	}
}

class Cooker implements Runnable {
	boolean hasFood;
	int value;

	@Override
	public void run() {
		for (int i = 1; i <= 5; i++) {
			// 将锁挂到同一个线程等待池中
			synchronized (this) {
				try {
					while (hasFood) {// 使用while是因为存在虚假唤醒,不能使用if
						/**
						 * 在没有被通知、中断或超时的情况下,线程还可以唤醒一个所谓的虚假唤醒 (spurious wakeup)。
						 * 虽然这种情况在实践中很少发生,但是应用程序必须通过以下方式防止其发生,
						 * 即对应该导致该线程被提醒的条件进行测试, 如果不满足该条件,则继续等待。换句话说,等待应总是发生在循环中
						 */
						this.wait();//wait方法会释放钥匙
					}
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				value = new Random().nextInt(1000);
				System.out.println("Cooker 生产食物 " + value);
				hasFood=true;
				this.notify();
			}
		}
	}
}

class Diners implements Runnable {
	private Cooker cooker;

	public Diners(Cooker cooker) {
		super();
		this.cooker = cooker;
	}

	@Override
	public void run() {
		for (;;) {
			// 将锁挂到同一个线程等待池中
			synchronized (cooker) {
				try {
					while(!cooker.hasFood){
						cooker.wait();
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
				System.out.println("Diners 消费食物 " + cooker.value);
				cooker.hasFood=false;
				cooker.notify();
			}
			
		}
	}
}


线程中的通讯:在实际的业务中的使用
public class ThreadDemo9 {
	public static void main(String[] args) {
		final Bussiness bus=new Bussiness();
		Thread t1=new Thread(new Runnable() {
			@Override
			public void run() {
				bus.send();
			}
		});
		Thread t2=new Thread(new Runnable() {
			@Override
			public void run() {
				bus.recived();
			}
		});t2.setDaemon(true);
		t1.start();
		t2.start();
	}
}

class Bussiness {
	boolean flag;
	int value;

	public void send() {
		for (int i = 0; i < 5; i++) {
			synchronized (this) {
				try {
					while (flag) {
						this.wait();
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
				value = new Random().nextInt(1000);
				System.out.println("send value is " + value);
				flag = true;
				this.notify();
			}
		}
	}

	public void recived() {
		while (true) {
			synchronized (this) {
				try {
					while (!flag) {
						this.wait();
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
				System.out.println("receive value is " + value);
				flag = false;
				this.notify();
			}
		}
	}
}

一个在处理缓存时候超级实用的例子
/*
 * @author vayne
 * 
 * 多线程实现缓存的小demo
 */
class Cachend
{
    volatile Map<String, String> cachmap = new HashMap<String, String>();//加volatile关键字保证可见性。

    ReadWriteLock rwLock = new ReentrantReadWriteLock();//这个读写锁要定义在方法外面,使得每一个线程用的是同一个读写锁。
    public  String getS(String key)                     //如果定义在方法内部,就是跟方法栈有关的读写锁。这样可能不是同一个锁。
    {
        rwLock.readLock().lock();
        String value = null;
        try
        {
            value = cachmap.get(key);

            if (cachmap.get(key) == null)//这里要重新获得key对应的value值
            {
                rwLock.readLock().unlock();
                rwLock.writeLock().lock();
                try
                {
                    if (cachmap.get(key) == null)//这里也是
                    {
                        value = "" + Thread.currentThread().getName();

                        cachmap.put(key, value);

                        System.out.println(Thread.currentThread().getName()  + "  put the value ::::" + value);
                    }
                } finally
                {
                    rwLock.readLock().lock();   //将锁降级,这里跟下一句的顺序不能反。
                    rwLock.writeLock().unlock();//关于这里的顺序问题,下面我会提到。
                }
            }

        } finally
        {
            rwLock.readLock().unlock();
        }

        return cachmap.get(key);
    }
}

分享到:
评论

相关推荐

    POSIX多线程程序设计.pdf

    《POSIX多线程程序设计》深入描述了IEEE的开放系统接口标准——POSIX线程,通常称为Pthreads标准。本书首先解释了线程的基本概念,包括异步编程、线程的生命周期和同步机制;然后讨论了一些高级话题,包括属性对象、...

    Win32 多线程程序设计完全手册PDF,本书详细讲解了多线程程序设计。

    《Win32多线程程序设计完全手册》是一本深入探讨Windows操作系统环境下多线程编程技术的专业书籍。在计算机科学中,多线程是并行处理的一种方式,它允许一个应用程序同时执行多个任务,从而提高了系统的效率和响应...

    多线程基础与基于多线程的简单聊天室

    在IT行业中,多线程是程序设计中的一个重要概念,尤其在Java编程中,它被广泛应用于提高应用程序的并发性能和响应速度。本压缩包“多线程基础与基于多线程的简单聊天室”提供了对多线程技术的实践理解和二次开发的...

    VC++简单的多线程聊天程序课程设计

    本课程设计项目旨在利用Visual C++(VC++)开发一个简单的多线程局域网聊天程序。随着互联网的发展,即时通讯软件如QQ、MSN等已经成为人们日常生活中的重要组成部分。这些软件的实现往往涉及到复杂的网络通信和多...

    Java多线程程序设计

    Java多线程程序设计是Java开发中的重要领域,它允许应用程序同时执行多个任务,从而提高系统资源的利用率和程序的响应速度。在Java中,多线程主要通过两种方式实现:继承Thread类和实现Runnable接口。 一、创建线程...

    大漠多线程模板_大漠_大漠多线程_

    在IT行业中,多线程是程序设计中的一个重要概念,特别是在C#编程中。"大漠多线程模板"是一个专门针对C#开发的多线程处理框架,它为开发者提供了便捷的方式来管理和优化多线程应用。这个框架由知名开发者"大漠"创建,...

    DELPHI下的多线程程序设计

    在 Delphi 中进行多线程程序设计是一项强大的技术,它允许开发者在同一个应用程序中同时执行多个任务,充分利用现代操作系统如 Win95 和 WinNT 的多线程特性。Delphi 2.0 提供了对多线程编程的良好支持,通过内置的 ...

    win32多线程程序设计 书中示例代码

    在Windows平台上进行多线程程序设计是开发高效并发应用程序的关键技术之一。侯捷先生的《win32多线程程序设计》是该领域的经典著作,深入浅出地讲解了如何在Win32环境下创建和管理多线程。下面将详细探讨多线程编程...

    Qt多线程程序设计

    ### Qt多线程程序设计详解 #### 一、Qt对多线程的支持 Qt作为一款功能强大的跨平台应用开发框架,对于多线程的支持是非常重要的。随着计算机硬件的发展,多核处理器越来越普及,多线程编程已成为现代软件开发中不...

    深入浅出Win32多线程程序设计.pdf

    ### 深入浅出Win32多线程程序设计 #### 基本概念与原理 《深入浅出Win32多线程程序设计》一书深入剖析了多线程编程的基础理论与实践技巧,尤其针对Win32平台进行了详尽的探讨。随着现代计算机系统的发展,多线程...

    POSIX多线程程序设计中文版

    - 通过具体的实例来展示如何使用POSIX API进行多线程编程,如简单的线程同步、线程池的构建等。 - 深入分析每个步骤中的关键代码和技术要点,帮助读者理解和掌握相关知识。 **2. 最佳实践** - 提供一系列最佳...

    多线程Web服务器的设计与实现

    Java语言提供了丰富的多线程API,如`Thread`类和`Runnable`接口,使得创建和管理线程变得简单。 2. **Web服务器工作原理**:一个典型的Web服务器接收到请求后,会解析HTTP报文,根据请求的方法(GET、POST等)来...

    Delphi中最简单的多线程例子

    本篇文章将详细讲解一个在Delphi中实现的最简单的多线程例子,帮助你理解如何在实践中应用多线程。 首先,让我们分析一下提供的文件列表: 1. `ThSort.dcu` 和 `SortThds.dcu`:这些是编译后的单元文件,包含了源...

    多线程编程示例

    在IT领域,多线程编程是一项关键技能,尤其是在性能优化和并发处理方面。本文将深入探讨多线程编程的基础知识,以帮助初学者快速入门。 首先,我们需要理解什么是多线程。多线程是指在一个进程中同时执行多个独立的...

    易语言多线程简单实用例子分享

    在这个“易语言多线程简单实用例子分享”中,我们将探讨如何在易语言中利用多线程技术来提高程序的运行效率和用户体验。 多线程是现代软件开发中的一个重要概念,它允许程序同时执行多个任务,而不是顺序地执行。在...

    OpenMP 多线程程序设计

    在Visual Studio 2005中,OpenMP被广泛用于编写多线程应用程序,以充分利用多核处理器的计算能力。下面我们将详细探讨OpenMP的核心概念、API以及如何在VS2005中使用OpenMP进行多线程编程。 1. **OpenMP的基本概念**...

    java 多线程简易聊天 精简版

    Java多线程技术是编程领域中的重要概念,尤其在开发高效、并发的网络应用程序时,如简易聊天程序,它的应用尤为关键。在这个“java 多线程简易聊天 精简版”项目中,我们将深入探讨Java如何实现多线程环境下的客户端...

    Linux系统下的多线程编程入门.pdf

    在Linux系统下进行多线程编程是开发高效并发应用程序的关键技术之一。本文将深入探讨Linux环境中的多线程概念、创建与管理线程的方法、线程同步与通信机制,以及多线程编程中可能遇到的问题和解决策略。 一、多线程...

Global site tag (gtag.js) - Google Analytics