http://www.ibm.com/developerworks/library/j-jtp0730/index.html
学习编程的目的:解决问题/开发用户需要的功能
多线程可以解决什么问题?
将不同的子任务交给不同的线程去执行,提高系统响应速度(比单一线程执行所有任务更快)
从最简单的开始,如何创建线程!
run() : 封装线程要运行的任务,所以将线程要运行的代码封装到run()中即可!
方式一:创建一个类直接继承Thread类,并覆盖run()
方式二:创建一个类实现Runnable接口,实现run(),再将此类的实例传入Thread构造方法中
开启线程:
new Thread().start();
new Thread(MyTask).start(); [ MyTask implements Runnable ]
线程的几种状态切换
两种使用线程的方式:
package thread; /** * 多线程使用方式一: * 通过继承Thread类让子类成为线程类 * 再通过该线程类开启线程执行任务 * */ public class ThreadDemo_A extends Thread { public ThreadDemo_A(String threadName) { //将线程名称传入父类构造方法,设置父线程的name,子类再将此name继承下来 super(threadName); } @Override public void run() {//run()封装线程需要执行的任务 for(int i=0;i<100;i++) { //获取当前线程名称 System.out.println(Thread.currentThread().getName()); } } public static void main(String[] args) { //主线程 System.out.println("main() start"); ThreadDemo_A a = new ThreadDemo_A("work_11111"); a.start();//开启另外1个线程 new ThreadDemo_A("work_22222").start();//再开启1个线程 System.out.println("main() end"); } }
推荐的方式--->通过Runnable封装线程任务
package thread; /** * 多线程使用方式二: * 通过实现 Runnable 接口,在run()中定义需要由线程执行的任务 * 然后将子类实例传递到Thread构造函数中,让Thread类去开启线程执行子类中的run() * */ public class ThreadDemo_B implements Runnable { private String address; private String content; public ThreadDemo_B() {} public ThreadDemo_B(String address, String content) { this.address = address; this.content = content; } @Override public void run() { sendEmail();//线程任务:发送邮件 } private void sendEmail() { for(int i=0;i<100;i++) System.out.println(Thread.currentThread().getName()+"------->>>>"+"Send email to " + address +", content=" + content); } public static void main(String[] args) { ThreadDemo_B task1 = new ThreadDemo_B("1@1.com", "1111111"); ThreadDemo_B task2 = new ThreadDemo_B("2@2.com", "2222222"); new Thread(task1,"线程111111").start(); new Thread(task2,"线程222222").start(); } }
==========================================================================
单个线程操作资源不存在同步、异步。
同步:WC,进入后上锁,出来后打开锁。
通过同步(加锁)来解决多线程操作共享资源时的安全问题!
同步的弊端:效率低(操作共享资源之前,线程都需要判断锁,如果锁没有释放,是进入不了的,会一直等待锁的释放)。
什么时候需要使用同步?
多个线程操作共享资源
且必须使用同一个锁,才能实现多线程同步访问的效果!
不同情况下的同一 个锁:
同步代码块使用的锁:堆内存中的任何相同对象(内存地址相同,即同一个对象)。
Runnable中定义一个成员对象,如 Object locker = new Object();
synchronized(locker)使用的就是同一个锁;
同步函数使用的锁:this
静态同步函数使用的锁:该方法所属类的字节码对象 Ticket.class
Java提供的处理同步问题的办法:
同步代码块
public void doIt() { doSomething.... //操作共享资源的代码,使用同步代码库对其封装 synchronized (Task.class) { ... } doOtherthing... }
同步函数
//使用同步函数封装那些涉及共享资源操作的代码 public synchronized void doIt() { //操作共享资源的代码 code... }
由于同步中使用的锁可以是任何对象,所以wait(),notify(),notifyAll()被定义在Object中!
wait(),notify(),notifyAll()是绑定在同一个锁上相互进行通信的!
wait() : 某种不满足操作的情况下,线程让自己进入等待状态!locker.wait()
notify(): 当线程自己进入等待状态后,调用notify()唤醒线程池中的一个线程,只唤醒一个(可能唤醒的是本方线程,造成死锁)。locker.notify()
notifyAll() : 唤醒线程池中所有等待的线程,可以避免死锁的发生。locker.notifyAll()
package thread; /** * 简单的2个线程间交替执行示例 * 通过synchronized保证对资源的“原子操作”不被打断 * 通过线程通信实现切换运行 */ public class TwoThreadsCommunication { public static void main(String[] args) { new TwoThreadsCommunication().justDoIt(); } public void justDoIt() { final ResourceHandler r = new ResourceHandler(); new Thread(new Runnable() { public void run() { for(int i=0;i<100;i++) r.produce(); } }, "线程A").start(); new Thread(new Runnable() { public void run() { for(int i=0;i<100;i++) r.consume(); } }, "线程B").start(); } /** * 资源类 * * 将多线程操作的代码单独封装起来,然后在run()中通过对象来调用 * 将同步放到资源上,而不是在run()中进行控制,实现与具体线程的解耦 * 互斥不要放到线程上进行,而应该放到对资源类操作的方法中!!! */ class ResourceHandler { //状态变量在资源内部进行操作 private boolean full; //生产线程操作共享资源的方法 public synchronized void produce() { //notice: 这里用while,不要用if。可防止死锁! while(full) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } for(int i=1;i<=10;i++) { System.out.println(Thread.currentThread().getName()+" run***" + i); } full = true; this.notify(); } //消费线程操作共享资源的方法 public synchronized void consume() { //notice: 这里用while,不要用if。可防止死锁! while(!full) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } for(int j=1;j<=10;j++) { System.out.println(Thread.currentThread().getName()+" run******" + j); } full = false; this.notify(); } } }
多线程间共享资源的方式:
package thread; /** * 多线程共享资源的方式一: * * 操作共享资源的run()放到内部类中,然后操作外部类中定义的资源 * * 1个线程负责加,1个线程负责减 */ public class ShareDataStyle1 { private int sharedData = 100; public synchronized void add() { sharedData++; System.out.println(Thread.currentThread().getName()+" add:" + sharedData); } public synchronized void minus() { sharedData--; System.out.println(Thread.currentThread().getName()+" minus:" + sharedData); } //内部类访问外部类的共享资源 class Add implements Runnable { public void run() { while(true) add(); } } //内部类访问外部类的共享资源 class Minus implements Runnable { public void run() { while(true) minus(); } } public static void main(String[] args) { ShareDataStyle1 sharedDate = new ShareDataStyle1(); new Thread(sharedDate.new Add()).start(); new Thread(sharedDate.new Minus()).start(); } }
package thread; /** * 多线程共享资源的方式二: * * 将共享资源传递到不同的Runnable对象中 * * 1个线程负责加,1个线程负责减 */ public class ShareDataStyle2 { public static void main(String[] args) { SharedData data = new SharedData(); new Thread(new Add(data)).start(); new Thread(new Minus(data)).start(); } } class SharedData { private int sharedData = 100; public synchronized void add() { sharedData++; System.out.println(Thread.currentThread().getName()+" add:" + sharedData); } public synchronized void minus() { sharedData--; System.out.println(Thread.currentThread().getName()+" minus:" + sharedData); } } class Add implements Runnable { SharedData sharedData; public Add(SharedData sharedData) { this.sharedData = sharedData; } public void run() { while(true) sharedData.add(); } } class Minus implements Runnable { SharedData sharedData; public Minus(SharedData sharedData) { this.sharedData = sharedData; } public void run() { while(true) sharedData.minus(); } }
异步:游泳池,往里跳,往外出,互不干扰,这就是异步。
同步:解决多个线程操作共享资源发生安全隐患!
A线程在执行某个代码片段,B线程在A线程释放锁之前将被阻塞(同一个监视器下)。
而异步呢:多个线程以并行工作的方式协同完成整体任务,目的是更快的完成当前任务!
一个耗时较长的任务,如果可以被分割为几个小的部分,而且这几个部分没有前后依赖关系,则可以并行的执行(充分利用多CPU的能力),提高处理速度。
=======================================================================
几个容易混淆的概念
wait : 当前线程将释放CPU,释放锁
sleep : 当前线程将释放CPU,不释放锁
InterruptedException:
线程当前所处状态被清除时,如,本来线程A正在sleep(5000),当到2000ms时,突然其sleep状态被清除了,此时,线程A将继续进行执行。只是,这种情况发生之后,JVM会抛出InterruptedException 到该线程上,告诉你线程A非正常醒了,是否需要处理这种非正常的醒就看程序员如果处理该异常了!
需要理解的是:发生InterruptedException不代表当前线程结束了!
一般情况下,这种非正常状态改变发生后,直接让方法return即可!
调用线程t的interrupt()便可以让t线程发生InterruptedException,然后在catch块中改变程序执行控制标记,或者return都行,具体怎么弄就看情况了!
守护线程:setDeamon(boolean b)
当所有线程都是守护线程时,JVM就会自动退出。
如,设置一个守护线程专门管理系统的缓存:
Thread cacheThread = new Thread(new CacheManager());
cacheThread.setDeamon(true); //必须在开启线程之前进行设置
cacheThread.start();
线程结合点:join()
切入一个新的线程到当前环境,只有切入的线程执行完毕后,当前线程才会继续执行
Thread subThread = new SubThread();
subThread.join();//直到subThread执行完毕,当前线程才继续往下执行
线程优先级
Thread t1 = new Thread();
t1.setPriority(Thread.MAX_PRIORITY);//最高优先级:10
Thread t2 = new Thread();
t2.setPriority(Thread.MIN_PRIORITY);//最低优先级:1
Thread t3 = new Thread();
t3.setPriority(Thread.NORM_PRIORITY);//默认优先级:5
线程组ThreadGroup
将若干功能相似的线程放到一个组中,便于统一管理。如统一设置优先级等
相关推荐
### C#多线程基础详解 #### 知识点一:多线程概念与优势 在C#中,多线程是指一个程序中同时执行多个线程的能力。一个线程是程序执行的基本单位,每个线程都有自己的指令指针、栈和局部变量,但共享相同的内存空间...
本压缩包“多线程基础与基于多线程的简单聊天室”提供了对多线程技术的实践理解和二次开发的基础。以下是关于这个主题的详细知识点: 1. **多线程的概念**:多线程是指在一个程序中同时执行多个不同的线程,每个...
在IT行业中,多线程是程序并发执行的一种方式,它极大地提高了系统资源的利用率和程序...在学习过程中,可以参考"多线程基础总结01.bmp"和"多线程基础总结01.mmap"等文件,它们可能提供了更为详细和直观的结构化知识。
本教程将深入探讨C#中的多线程基础,包括创建线程、线程同步与通信、线程池以及线程安全等内容。 一、线程创建 在C#中,有两种主要方式来创建线程:使用`System.Threading.Thread`类和使用`System.Threading.Tasks...
这个"JAVA多线程基础演练DEMO"提供了一些基础示例,帮助开发者更好地理解和掌握多线程的基本概念和用法。以下将详细讲解Java多线程的相关知识点: 1. **线程的创建** - **继承Thread类**:创建一个新类,继承自`...
通过学习和掌握这些多线程基础知识,开发者能够编写出更加高效、稳定的并发程序,提升软件系统的性能和用户体验。同时,对多线程深入理解也有助于应对面试中的技术考察,为职业生涯的晋升铺平道路。
Java多线程是Java编程中的一个...以上只是Java多线程基础知识的一部分,深入学习还包括线程池的配置与优化、线程安全的设计模式、并发工具类的使用等。理解和掌握这些知识点对于编写高效、稳定的多线程程序至关重要。
C#多线程是编程中的重要概念,尤其在开发高性能...总的来说,理解和掌握C#多线程基础知识对于编写高效、健壮的程序至关重要。在实际开发中,应合理利用多线程,注意线程安全,避免潜在的问题,提升软件的稳定性和性能。
**多线程基础** 多线程是指在一个进程中可以同时运行多个独立的执行流,每个执行流被称为一个线程。在MFC中,我们可以使用`CWinThread`类来创建和管理线程。`CWinThread`是MFC对Windows API中的`_beginthreadex`和`...
Java多线程基础篇讲解是针对初学者设计的教程,旨在用简洁明了的语言帮助学习者更容易理解多线程的概念和应用。多线程编程在现代计算机系统中扮演着重要角色,尤其在CPU主频发展遇到瓶颈的情况下,通过超线程技术和...
"多线程基础代码.rar"这个压缩包文件很可能是包含了一些关于多线程编程的基础示例代码,用于帮助初学者理解和实践多线程技术。 多线程允许一个应用程序同时执行多个不同的任务,每个任务被称为一个线程。在Java、C#...
头歌java多线程基础 “头歌”是一个在线教育平台,提供包括Java在内的多种编程语言的在线学习资源和课程。Java多线程基础是学习Java编程中非常重要的一部分,它涉及到如何同时运行多个任务,以充分利用现代多核...
我们将围绕标题“多线程基础部分”展开,结合描述和标签,重点关注Java中的多线程、软件设计以及并发编程的相关概念。 首先,让我们理解什么是多线程。在计算机科学中,线程是程序执行的基本单位,一个进程可以包含...
Java多线程基础知识 Java多线程基础知识是Java编程语言中的一项重要技术,用于提高程序的执行效率和响应速度。在这里,我们将详细介绍Java多线程基础知识的相关概念和技术。 一、程序、进程和线程 程序(Program...
多线程基础理论, 多线程中常用API,多线程的实现方式, 线程池以及创建线程池相关API, 常见的设计模式等内容
本教程将深入探讨C#中的多线程基础知识,以及如何通过实例来实现线程的控制和通信。 首先,我们需要理解线程的基本概念。在操作系统中,线程是执行单元,它代表程序的一个执行流程。每个线程拥有自己的栈空间,用于...
对于初学者来说,理解并掌握多线程基础编程至关重要,因为这能帮助他们构建更加高效和复杂的软件系统。在这个"VC++多线程基础编程源程序"中,我们将探讨如何利用Visual Studio 2008来实现多线程功能,特别是通过创建...
Java多线程是Java编程中的重要...以上内容仅涵盖了Java多线程基础编程的一部分知识点,实际开发中还需要关注更多的并发控制策略、性能优化和调试技巧。对于深入理解Java多线程,还需要学习和实践更多相关的高级特性。
C# 多线程基础练习,需要学习多线程的小伙伴们快来下载吧