`
xiaozhouzhou
  • 浏览: 13359 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

多线程初谈——线程的创建与互斥问题

 
阅读更多
多线程初谈——线程的创建与互斥
     对于线程起初也很是不解,觉得很乱,线程的互斥就跟别提了。创建线程也一直只能通过创建Thread子类的方法,像那个实例化Runnable对象一直不是很理解,也没敢用,二者的线程创建区别在哪也不清楚。带着这些困惑一直到了现在。随着对Android语言的深入学习,发现线程真的很重要,不弄清楚就难以做出一个好的产品,不解决线程的互斥,同步通信,死锁问题,就无法得到一个高质量,高安全的东西。所以趁着国庆期间把线程同步这一块重新学习了一遍。以下是我在学习过程中做出的一些总结,希望对还在苦恼的你有些许帮助。一、创建线程的两种方法:
1、通过创建Thread子类来实现线程:创建Thread子类,子类中重写run方法覆盖掉父类的run方法。
2、实例化Runnable对象来实现线程:给Thread类的构造函数传一个Runnable对象,再调用Runnable对象中的run方法。(Runnable对象不是线程,是线程要运行的代码的宿主)

如果对于第二种方法不是很理解,对于为什么要实例化Thread类,再加入对象Runnable有疑问.像代码:
Thread thread=new Thread(new Runnable(){
			@Override
			public void run() {
				// TODO Auto-generated method stub
			}
		});

下面给出一段源代码,我想你这时就知道为什么是这样了。
public Thread(Runnable target) {
        init(null, target, "Thread-" + nextThreadNum(), 0);
    }
public void run() {
        if (target != null) {
            target.run();
        }
    }

由此可见,实例化Runnable接口来创建线程的实质就是,把run方法封装入Runnable对象,再通过Thread的构造方法将Runnable对象传入

二、两种方法的些许不同:
第二种方法更趋向于面向对象。我们在编码的过程中是面向对象的,第二种方法,是把run方法封装到一个独立对象Runnable中去,然后放入线程对象Thread中.当然在创建线程时,两种方法都是可以的。
下面给出一段线程创建代码,以供参考

public static void main(String args[]){
		/*
		 * 通过创建Thread子类的的构造线程的方法
		 */
		Thread thread=new Thread(){
			//重写父类的run方法
			public void run(){
				while(true){
					try {
						//线程休眠0.5秒
						Thread.sleep(500);
					} catch (Exception e) {
						e.printStackTrace();
					}
					//打印当前线程名
					System.out.println(Thread.currentThread().getName());
				}
			}
		};
		thread.start();//线程启动
		
		/*
		 * 实例化Runnable对象,传入Thread类中来创建线程
		 */
		Thread thread2=new Thread(new Runnable(){

			
			public void run() {
				while(true){
					try {
						//线程休眠0.5秒
						Thread.sleep(500);
					} catch (Exception e) {
						e.printStackTrace();
					}
					//打印当前线程名
					System.out.println(Thread.currentThread().getName());
				}
			}
		});
		thread2.start();//线程启动
		

		
	}

其运行结果


如果你觉得对两者的创建及些许的区别有很好的了解,那就思考下,下面的代码会输出什么样的结果:
//创建Thrad子类
new Thread(new Runnable(){//创建Runnable对象,传入Thread中
	public void run() {
		while(true){
			try {
				//线程休眠0.5秒
				Thread.sleep(500);
			} catch (Exception e) {
				e.printStackTrace();
			}
			//打印当前线程名
			System.out.println("runnable:"+Thread.currentThread().getName());
		}
	}
	
}){
	public void run() {
		while(true){
			try {
				//线程休眠0.5秒
				Thread.sleep(500);
			} catch (Exception e) {
				e.printStackTrace();
			}
			//打印当前线程名
			System.out.println("thread:"+Thread.currentThread().getName());
		}
	}
}.start();//开启线程
运行结果:


--------------------------------分割线-------------------------------
三、线程的互斥问题。
线程的互斥就是一个关键字:synchornized.互斥锁定的必须是同一个对象,必须是同一个锁。
我们在用到多线程操作同一份数据时,就会用上线程的互斥,如果这块不懂的话,代码会出现很严重的逻辑问题和产品安全性问题。就如银行的存取款,如果我原有1000元存款,现在父母往里面又存了500元,同时我在取钱200,如果银行系统线程同步没处理好,那么就很可能出现自己的存款总后只有800元,而不是1300.
下面给出没有加线程互斥的代码:
public class SteupThread {
	
	public static void main(String args[]){
		new SteupThread().init();
	}
	public void init(){
	//内部类不能访问局部变量,为了访问局部变量,需加final
	final Output output=new Output();
		//线程1
		new Thread(new Runnable(){
			public void run() {
				while(true){
					try {
						Thread.sleep(500);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					output.print1("wobeidayinle");
				}
			}
			
		} ).start();
		
		//线程2
		new Thread(new Runnable(){
			public void run() {
				while(true){
					try {
						Thread.sleep(500);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					output.print2("howareyou");
				}
			}
			
		} ).start();
	}
	//内部类
	class Output{
		public void print1(String st){
			int len=st.length();
			for(int i=0;i<len;i++){
				System.out.print(st.charAt(i));
			}
			System.out.println();
		}
		public void print2(String st){
			int len=st.length();
			for(int i=0;i<len;i++){
				System.out.print(st.charAt(i));
			}
			System.out.println();
		}
	}
}

运行结果


通过上面的代码可以知道:在打印语句:howareyou时被打断了,为了避免此类事情发生,就必须用到线程的互斥了。
代码改进如下:
将内部类Output中的同步方法用synchornized锁定
//内部类
	class Output{
		public synchronized void print1(String st){
			int len=st.length();
			for(int i=0;i<len;i++){
				System.out.print(st.charAt(i));
			}
			System.out.println();
		}
		public synchronized void print2(String st){
			int len=st.length();
			for(int i=0;i<len;i++){
				System.out.print(st.charAt(i));
			}
			System.out.println();
		}
	}


线程的创建与互斥就总结到此,如果觉得这些简单,认为学懂了线程的互斥,就思考一下这个问题怎么解决吧:
问:子线程循环10次,接着主线程循环100次,接着又子线程循环10次,然后又主线程循环100次,如此循环50次,请写出相应程序。(此为一次公司招聘面试题!如果没有解决,后面会给出代码,此类为线程同步通信问题。)
  • 大小: 12.1 KB
  • 大小: 13.3 KB
  • 大小: 12.9 KB
1
3
分享到:
评论

相关推荐

    操作系统实验——进程的同步与互斥(读者写者问题)

    以生产者消费者模型为基础,在Windows环境下创建一个控制台进程,在该进程中创建读者写者线程模拟生产者和消费者。写者线程写入数据,然后将数据放置在一个空缓冲区中供读者线程读取。读者线程从缓冲区中获得数据,...

    操作形同实验——进程同步和互斥

    操作形同实验——进程同步和互斥 (1) 通过编写程序实现进程同步和...(2) 了解Windows2000/XP中多线程的并发执行机制,线程间的同步和互斥。 (3) 学习使用Windows2000/XP中基本的同步对象,掌握相应的API函数。

    多线程编程——互斥锁使用(Jack_pthread_mutex_test.rar)

    多线程编程:互斥锁使用。 打包文件包含两个文件:c文件源代码、Makefile文件,运行环境在Ubuntu14.04下,使用自带的gcc编译器,同学们只需将文件夹复制到某一目录下之后在终端执行:1.“make”生成“test”可执行...

    秒杀多线程第十六篇 多线程十大经典案例之一 双线程读写队列数据

    在《秒杀多线程系列》的前十五篇中介绍多线程的相关概念,多线程同步互斥问题《秒杀多线程第四篇一个经典的多线程同步问题》及解决多线程同步互斥的常用方法——关键段、事件、互斥量、信号量、读写锁。为了让大家...

    java多线程设计模式详解(PDF及源码)

    单线程程序 多线程程序 Thread类的run方法和start方法 线程的启动 线程的启动(1)——利用Thread类的子类 线程的启动(2)——利用Runnable接口 线程的暂时停止 线程的共享互斥 synchronized方法 synchronized阻挡 ...

    并发服务器II——多线程

    POSIX 线程库Pthreads介绍 POSIX pthreads库提供的基本线程的操作 线程的属性 线程互斥和同步 使用GDB 调试线程以及线程的调优 多线程网络服务器模型 试验题目

    《Visual C++范例大全》随书光盘 第十一章

    实例269——使用多线程进行文件搜索 实例270——获取当前系统的所有进程 实例271——实现应用程序在系统中只能运行一个实例 实例272——获取所有打开窗口程序的句柄、类名及标题 实例273——创建和终止进程 ...

    Java线程间同步互斥

    摘要:Java源码,系统相关,线程同步,线程互斥 Java线程间同步互斥,在实际的编程中,经常要处理线程间的同步互斥问题。Java 语言内在强大的多线程支持使得处理这类问题变得相对来说比较简单。本例将模仿经典的线程...

    VC++秒杀多线程,双线程读写队列数据

    摘要:VC/C++源码,系统相关,多线程同步 多线程十大经典案例之一秒杀多线程,多线程同步互斥问题《秒杀多线程第四篇一个经典的多线程同步问题》及解决多线程同步互斥的常用方法——关键段、事件、互斥量、信号量、...

    Java多线程编程 线程同步机制.docx

    线程安全问题的产生是因为多个线程并发访问共享数据造成的,如果能将多个线程对共享数据的并发访问改为串行访问,即一个共享数据同一时刻只能被一个线程访问,就可以避免线程安全问题。锁正是基于这种思路实现的一种...

    操作系统课程设计——模拟生产者与消费者(java)

    掌握线程创建和终止的方法,加深对线程和进程概念的理解,会用同步与互斥方法实现线程之间的进行操作。 在学习操作系统课程的基础上,通过实践加深对进程同步的认识,同时,可以提高运用操作系统知识解决实际问题的...

    操作系统——Linux信号量机制

    在Linux环境下实现一个多线程对临界资源的互斥操作,利用信号量实现对临界资源的保护,支持Linux下文件输入输出,提高对Linux环境下多进程、多线程、信号量机制和文件操作等知识的理解。 设有进程A、B、C,分别调用...

    Visual C++实践与提高——串口通信与工程应用篇1

    4.1.3 多线程串口的应用 78 4.2 线程的操作 78 4.2.1 创建线程 78 4.2.2 终止线程 80 4.2.3 关于内存泄漏 81 4.3 线程间通信 81 4.3.1 使用全局变量 81 4.3.2 使用自定义消息 81 4.4 线程同步 82 4.4.1 使用临界区...

    疯狂内核之——进程管理子系统

    1.2 Linux的线程——轻量级进程 15 1.3 进程的创建——do_fork()函数详解 19 1.4 执行进程间切换 33 1.4.1 进程切换之前的工作 33 1.4.2 进程切换实务 —— switch_to宏 37 1.4.3 __switch_to函数 39 1.5 fork与...

    C#源码大集合 02(共3卷)

    ├─Windows多线程编程技术与实例 ... ... ├─多线程,多接收模式串口类 ├─多线程文件传输 ├─多线程的日志记录DLL ├─多线程端口扫描程序 ├─多线程,多接收模式串口类 ├─实例10-多线程实例 ├─实例12-多...

    进程间通信经典——银行柜员服务问题

    Windows下解决经典的银行柜员服务问题,使用PV原语实现线程间同步和互斥,C++代码,下载后可直接运行

    数据结构算法

    Parallel的使用 多线程系列(5)5天不再惧怕多线程——第五天 线程池 5天不再惧怕多线程——第四天 信号量 5天不再惧怕多线程——第三天 互斥体 5天不再惧怕多线程——第二天 锁机制 5天不再惧怕多线程——第一天 尝试...

    c#入门经典范例50讲

    第12讲 多线程的互斥(一) 第13讲 多线程的互斥(二) 第14讲 多线程的互斥(三) 数据库应用程序开发 第15讲 显示数据库信息 第16讲 数据库导航 第17讲 参数化查询 第18讲 主从数据库显示 第19讲 读取XML文件 ...

    C#源码大集合 01(共3卷)

    ├─第53讲 文件系统监视器 │ └─第55讲 聊天室扩展之三——使用MS Agent &lt;br&gt;└ C#源代码第三部分多线程 ├─1-多线程 ├─2-多线程 ├─3-多线程互斥 ├─4-多线程互斥 ├─5-多线程...

Global site tag (gtag.js) - Google Analytics