- 浏览: 13939 次
- 性别:
最新评论
多线程初谈——线程的创建与互斥
对于线程起初也很是不解,觉得很乱,线程的互斥就跟别提了。创建线程也一直只能通过创建Thread子类的方法,像那个实例化Runnable对象一直不是很理解,也没敢用,二者的线程创建区别在哪也不清楚。带着这些困惑一直到了现在。随着对Android语言的深入学习,发现线程真的很重要,不弄清楚就难以做出一个好的产品,不解决线程的互斥,同步通信,死锁问题,就无法得到一个高质量,高安全的东西。所以趁着国庆期间把线程同步这一块重新学习了一遍。以下是我在学习过程中做出的一些总结,希望对还在苦恼的你有些许帮助。一、创建线程的两种方法:
1、通过创建Thread子类来实现线程:创建Thread子类,子类中重写run方法覆盖掉父类的run方法。
2、实例化Runnable对象来实现线程:给Thread类的构造函数传一个Runnable对象,再调用Runnable对象中的run方法。(Runnable对象不是线程,是线程要运行的代码的宿主)
如果对于第二种方法不是很理解,对于为什么要实例化Thread类,再加入对象Runnable有疑问.像代码:
下面给出一段源代码,我想你这时就知道为什么是这样了。
由此可见,实例化Runnable接口来创建线程的实质就是,把run方法封装入Runnable对象,再通过Thread的构造方法将Runnable对象传入。
二、两种方法的些许不同:
第二种方法更趋向于面向对象。我们在编码的过程中是面向对象的,第二种方法,是把run方法封装到一个独立对象Runnable中去,然后放入线程对象Thread中.当然在创建线程时,两种方法都是可以的。
下面给出一段线程创建代码,以供参考。
其运行结果:
如果你觉得对两者的创建及些许的区别有很好的了解,那就思考下,下面的代码会输出什么样的结果:
--------------------------------分割线-------------------------------
三、线程的互斥问题。
线程的互斥就是一个关键字:synchornized.互斥锁定的必须是同一个对象,必须是同一个锁。
我们在用到多线程操作同一份数据时,就会用上线程的互斥,如果这块不懂的话,代码会出现很严重的逻辑问题和产品安全性问题。就如银行的存取款,如果我原有1000元存款,现在父母往里面又存了500元,同时我在取钱200,如果银行系统线程同步没处理好,那么就很可能出现自己的存款总后只有800元,而不是1300.
下面给出没有加线程互斥的代码:
运行结果:
通过上面的代码可以知道:在打印语句:howareyou时被打断了,为了避免此类事情发生,就必须用到线程的互斥了。
代码改进如下:
将内部类Output中的同步方法用synchornized锁定。
线程的创建与互斥就总结到此,如果觉得这些简单,认为学懂了线程的互斥,就思考一下这个问题怎么解决吧:
问:子线程循环10次,接着主线程循环100次,接着又子线程循环10次,然后又主线程循环100次,如此循环50次,请写出相应程序。(此为一次公司招聘面试题!如果没有解决,后面会给出代码,此类为线程同步通信问题。)
对于线程起初也很是不解,觉得很乱,线程的互斥就跟别提了。创建线程也一直只能通过创建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次,请写出相应程序。(此为一次公司招聘面试题!如果没有解决,后面会给出代码,此类为线程同步通信问题。)
发表评论
-
线程的同步通信与线程范围内的数据共享问题
2013-10-02 22:05 1349线程的同步通信与线程范围内的数据共享问题一、线程的同步通信 什 ... -
网络通信见解之谈
2013-07-17 13:38 658一、网络通信的基本原理 现如今,出现了各式各样的聊天平 ... -
简单的bmp文件打开与保存
2013-07-01 22:24 916简单的bmp文件打开与保 ... -
分形浅谈——科赫曲线和L-System
2013-06-24 22:47 1261分形浅谈开始接触到分行图时,感觉很难,无法下手,只能做出第一层 ... -
对关键字final、static的理解
2013-05-10 23:36 574一、final关键字 fin ... -
对关键字的理解——访问权限
2013-05-10 16:17 627关键字public、pr ... -
队列的定义及运用
2013-03-23 14:58 728队列简称队,是限制在表的一端进行插入操作,而在表的另一端进行删 ... -
重绘方法的重写利用
2013-03-22 21:44 649重绘是为了在画布上保留原始痕迹的一种方法,他的目的是用来保存你 ... -
数组的定义及递归的运用
2013-03-22 21:43 1056一、数组有一维数组、 ... -
监听器与变量的作用域
2013-03-22 21:41 737监听器是用来实现一些可控操作的工具,如你在打开一个QQ界面的时 ... -
java中的继承
2013-03-08 00:31 588Java中的接口 什么是接口?不是以class定义的类而是以i ... -
Java中类的继承、重写、自动转型以及多态
2013-03-06 01:13 748Java中类的继承、重写、自动转型以及多态 1) 类的继承 在 ... -
java的构造器方法、方法重载和引用传递
2013-03-04 23:55 765Java的构造器方法、方法重载与引用传递 一、 构造器方法 构 ... -
JAVA语言中的类与对象
2013-03-04 00:08 763Java语 ...
相关推荐
以生产者消费者模型为基础,在Windows环境下创建一个控制台进程,在该进程中创建读者写者线程模拟生产者和消费者。写者线程写入数据,然后将数据放置在一个空缓冲区中供读者线程读取。读者线程从缓冲区中获得数据,...
操作形同实验——进程同步和互斥 (1) 通过编写程序实现进程同步和...(2) 了解Windows2000/XP中多线程的并发执行机制,线程间的同步和互斥。 (3) 学习使用Windows2000/XP中基本的同步对象,掌握相应的API函数。
多线程是现代计算机编程中的一个重要概念,尤其在操作系统如Windows这样的多任务环境中,多线程使得程序能够并发执行多个任务,从而充分利用系统的计算资源,提高程序的响应速度和效率。在C#编程中,多线程机制是...
#### 一、多线程问题提出 在软件开发过程中,经常会遇到一些耗时较长的任务,例如网络请求、文件读写等。这些任务如果在一个单线程环境下运行,很容易导致整个应用程序在执行这些任务期间变得无响应,即所谓的...
"MutiTread"这个文件可能包含了关于使用互斥量实现同步的具体示例代码或教程,可以帮助学习者深入理解如何在VC++ 6.0环境中创建和管理线程,以及如何利用互斥量解决多线程同步问题。通过实践这些示例,学习者可以更...
在“操作系统实验 多线程同步与互斥 java编写 有界面”的实验中,可能需要设计一个图形用户界面(GUI),通过按钮或事件触发线程的创建和同步操作,直观地展示线程间的交互和同步效果。例如,可以模拟银行账户转账,...
3. **同步与通信**:在多线程环境下,线程间的同步和通信是非常关键的。例如,使用互斥锁(mutex)防止多个线程同时访问同一数据,条件变量(condition variable)用于线程间的协调,信号量(semaphore)控制资源的...
本教程将深入讲解Java线程的相关知识,包括进程与线程的基本概念、线程的创建和启动、多线程的互斥与同步、线程状态和线程控制以及死锁的概念。 首先,我们要理解进程与线程的区别。进程是操作系统资源分配的基本...
值得注意的是,多线程编程会引入竞态条件、死锁和资源争抢等问题,因此需要特别注意线程安全。在访问共享资源时,应使用互斥量或者临界区(CCriticalSection)进行保护,避免数据不一致。 此外,MFC还提供了一些...
在“多线程编程之四——线程的同步”这个文件中,可能包含了上述各种同步机制的具体实现示例和详细说明,这对于初学者来说是一份非常宝贵的参考资料。通过学习和理解这些例子,开发者可以更好地掌握如何在实际项目中...
多线程编程:互斥锁使用。 打包文件包含两个文件:c文件源代码、Makefile文件,运行环境在Ubuntu14.04下,使用自带的gcc编译器,同学们只需将文件夹复制到某一目录下之后在终端执行:1.“make”生成“test”可执行...
接下来我们将通过一个具体的例子——“厨师-食客”模式来深入理解多线程编程的实际应用。 1. **模型介绍**: - 生产者(厨师):负责制作食物,并将其放入共享的“仓库”(桌子)。 - 消费者(食客):从“仓库”...
本教程“Visual C++高级编程技术——MFC与多线程篇”将深入探讨这两个关键概念。 MFC是C++面向对象编程的一个重要框架,它基于Windows API,将复杂的Win32 API函数封装为易于理解和使用的类。MFC包含了一系列的类,...
在C++编程中,多线程同步是一种关键的技术,它允许多个执行线程协同工作,以避免数据竞争和死锁等并发问题。信号量(Semaphore)是实现多线程同步的一种有效工具,常用于控制对共享资源的访问。在这个名为"Mthread11...
操作系统实验报告——进程同步与互斥 本实验报告的主要目的是掌握基本的进程同步与互斥算法,理解生产者-消费者问题,并学习使用 Windows 2000/XP 中基本的同步对象,掌握相关 API 的使用方法。 一、进程同步与...
操作系统实验报告——进程同步与互斥 该实验报告的目的旨在掌握基本的进程同步与互斥算法,理解生产者-消费者问题,并学习使用 Windows 2000/XP 中基本的同步对象,掌握相关API 的使用方法。实验环境采用 Windows ...