在项目中使用多线程的场景并不是很多,我想是一般项目对线程要求不高,但是线程在实际开发中带来的好处是很多的:
1.一件事:用单线程可以做,但是使用多线程可以更快。
2.典型应用tomcat,tomcat内部采用的就是多线程,上百个客户端访问同一个web应用,tomcat接入后都是把后续的处理扔给一个新的线程来处理,这个新的线程最后调用到我们的servlet程序,比如doGet或者doPost方法。
迅雷多任务下载,word, 浏览器,
3.后台线程:比如定期执行一些特殊任务,如定期更新配置文件,任务调度(如quartz),一些监控用于定期信息采集等。
4.数据库连接,每个session是一个线程
例子:原来售票系统只有一个窗口,现在5个窗口同时售票,缩短了排队时间。
需要考虑的事情:
(1)、多线程与多对象的关系
(2)、多线程与单例的关系
(3)、线程锁的应用与场景
1、为什么不创建多个实例(为什么使用单例)?
(1)、java 中,单例的使用往往是源于某些 bean 被频繁的使用,而且,创建它们的成本消耗很高。 例如:hibernate 中 SessionFactory ,单例模式就是为了保证它们不被重复创建,因为这是没有必要的。
(2)、控制实例产生的数量,达到节约资源的目的。
(3)、成员变量的共享,只属于单个实例享用,其他实例不能操作该变量,实现线程之间的资源共享。
减少系统资源的消耗.因为这种工具类基本上贯穿程序始终,必然会频繁调用,如果每一次调用都要重新生成实例,带来的就是在内存堆中存在大量此类实例,.所以这种模式会提高程序的运行速度,减少资源消耗;
2、为什么要使用多线程(多线程的优点)?
一、线程安全与不安全
简单demo:
public static void main(String[] args) {
//构造方法
Runnable runnable = new Runnable() {
Count count = new Count();
public void run() {
count.count();
System.out.println(count);
}
};
for(int i = 0; i < 10; i++) {
//构造方法
new Thread(runnable).start();
}
}
}
class Count {
private int num;
public void count() {
for(int i = 1; i <= 10; i++) {
num += i;
}
System.out.println(Thread.currentThread().getName() + "-" + num);
}
}
分析上面的线程是否安全:
1、变量num是成员变量,可以供所有线程使用,当一个线程此时通过运算得到num=46,而仅仅被下个线程执行后变成了47,再执行++时就变成了48,就造成num的不确定性,故不是安全的。
变量定义在方法内也就是局部变量是线程安全的。
2、看上去每个线程里都有一个new关键字,但从打印信息上看,他们是同一个实例,这样的易读性不好。应当将count拿出去, final Count count = new Count();
二、同步
Java线程的两个特性,可见性和有序性。多个线程之间是不能直接传递数据交互的,它们之间的交互只能通过共享变量来实现。上个列子中,在多个线程之间共享了Count类的一个对象,这个对象是被创建在主内存(堆内存)中,
每个线程都有自己的工作内存(线程栈),工作内存存储了主内存Count对象的一个副本,当线程操作Count对象时,首先从主内存复制Count对象到工作内存中,然后执行代码count.count(),改变了num值,
最后用工作内存Count刷新主内存Count。当一个对象在多个内存中都存在副本时,如果一个内存修改了共享变量,其它线程也应该能够看到被修改后的值,此为可见性。多个线程执行时,CPU对线程的调度是随机的,我们不知道当前程序被执行到哪步就切换到了下一个线程,一个最经典的例子就是银行汇款问题,一个银行账户存款100,这时一个人从该账户取10元,同时另一个人向该账户汇10元,那么余额应该还是100。那么此时可能发生这种情况,A线程负责取款,B线程负责汇款,A从主内存读到100,B从主内存读到100,A执行减10操作,并将数据刷新到主内存,这时主内存数据100-10=90,而B内存执行加10操作,并将数据刷新到主内存,最后主内存数据100+10=110,显然这是一个严重的问题,我们要保证A线程和B线程有序执行,先取款后汇款或者先汇款后取款,此为有序性。
Java中使用synchronized保证一段代码在多线程执行时是互斥的,有两种用法:
1、锁定对象;public void output(String name) {
synchronized (this) {
2、锁定方法:public synchronized void output(String name) {
使用synchronized修饰的方法或者代码块可以看成是一个原子操作,一个线程执行互斥代码过程如下:
1. 获得同步锁;
2. 清空工作内存;
3. 从主内存拷贝对象副本到工作内存;
4. 执行代码(计算或者输出等);
5. 刷新主内存数据;
6. 释放同步锁。
public static void main(String[] args) {
final Outputter output = new Outputter();
new Thread() {
public void run() {
output.output("zhangsan");
};
}.start();
new Thread() {
public void run() {
output.output("lisi");
};
}.start();
}
}
class Outputter {
public synchronized void output(String name) {
for(int i = 0; i < name.length(); i++) {
System.out.print(name.charAt(i));
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
三、线程协作
四、死锁
分享到:
相关推荐
GBase8s 线程介绍 GBase8s 线程是 GBase8s 数据库的核心组件之一,负责执行各种数据库操作。线程是操作系统的基本概念,它是操作系统分配 CPU 时间的基本单位。在 GBase8s 中,线程运行在数据库 VP(虚拟处理器)上...
8. **死锁(Deadlock)**:多个线程互相等待对方释放资源导致的僵局,需要谨慎设计并发逻辑以避免这种情况。 9. **中断线程**:线程可以通过`interrupt()`方法请求中断,但这并不立即终止线程,而是设置一个中断...
1.进程和线程是啥? 进程:进程就是一个应用程序,对电脑的各种资源的占用 线程:线程是程序执行的最小单位,任何操作都是线程完成的,线程依托...例如计算机是4核8线程中,核指的就是物理的核,线程指的是物理的核。
进程与线程的区别 - 博客园.mht 进程与线程的区别 - 博客园.mht 进程与线程的区别 - 博客园.mht
6-8线程最快大概400-500个链接每分钟 2-4线程最快大概200-400个链接每分钟 单线程最快大概70-100个链接每分钟 之所以用多线程异步抓取完全是出于效率考虑,本程序多线程同步并不能带来速度的提升,只要抓取的...
在本项目中,我们关注的是利用Python实现的“m3u8多线程下载器”。M3U8是一种基于HTTP/HTTPS协议的流媒体格式,常用于在线视频播放,尤其在移动设备上。它将视频文件分割成多个小片段,方便流式传输。 这个下载器...
在“stm32f103c8t6移植RT-Thread之线程管理”这个主题中,我们将探讨如何在STM32F103C8T6上创建和管理线程,以及线程如何与裸机程序相比提供更高级别的抽象和灵活性。 首先,我们需要了解RT-Thread的内核启动流程,...
本实验"java多线程之赛马程序实验8多线程练习下载进度"聚焦于如何利用多线程来模拟实际场景中的下载进度显示。在这一过程中,我们将探讨Thread类的`run`和`start`方法,以及如何通过进度条来可视化表示下载过程。 ...
8. **安全提示**: 多线程编程需要注意线程安全,避免数据竞争和死锁等问题。使用线程时需谨慎处理共享资源,确保同步机制正确无误。 通过以上介绍,我们可以理解易语言中多线程的基本操作和控制线程数量的方法。...
8. **性能优化**:多线程设计时要考虑系统的负载平衡,避免过多线程导致上下文切换开销过大。合理的线程池设计可以提高效率。 9. **线程退出**:在适当的时候,线程需要优雅地退出,释放占用的资源。可以设置退出...
8. **并发集合**:C#提供了线程安全的集合,如`ConcurrentQueue`、`ConcurrentStack`和`ConcurrentDictionary`,它们在多线程环境下保证数据一致性。模板可能利用这些集合来安全地共享数据。 9. **性能监控**:在多...
8. Volatile关键字: Volatile关键字可以保证线程间变量的可见性,但不能保证原子性。在多线程环境下,如果一个变量被多个线程共享且只进行读写操作,可以使用volatile保证数据的一致性。 9. sleep(), yield(), ...
8. **错误处理**:在多线程编程中,错误处理和异常安全是非常重要的。确保每个线程都有适当的错误处理机制,并在必要时进行资源清理。 通过以上步骤,我们可以在MFC环境中实现UI线程和工作线程的协同工作,使得在...
在Java编程语言中,创建线程是实现并发执行任务的关键步骤。Java提供了两种主要的方法来创建线程,分别是直接继承自`Thread`类和实现`Runnable`接口。这两种方法各有其特点和适用场景。 1. **继承Thread类**: 当...
在Delphi XE8开发环境中,多线程技术是一种常用的方法来提高应用程序的性能和响应性,特别是对于处理耗时任务或并发操作的情况。本文将深入探讨如何在Delphi XE8中使用多线程,以`TThreadTimer`为例进行讲解。 首先...
8. **MultiPanel**:在提供的压缩包文件名中提到的“MultiPanel”,可能是指LabWindows CVI中的多面板功能,它允许在一个应用程序中同时显示和操作多个独立的视图。在多线程编程中,每个面板可能对应一个独立的线程...
哈工大的操作系统实验8着重探讨了如何在内核层面实现线程机制,这对于理解和掌握操作系统的工作原理至关重要。 在操作系统中,线程是程序执行的基本单位,它代表了CPU调度的基本单元。与用户级线程(User-Level ...
8. **线程错误处理**:由于多线程可能引发各种异常,因此在编写多线程程序时,良好的错误处理策略是必不可少的。VB 6.0提供`On Error`语句来进行错误处理。 通过这个简单的VB 6.0多线程实例,你可以学习到如何利用...
8. Task并行库(TPL): .NET Framework 4.0引入了Task Parallel Library,提供了一种更高级的方式来并行执行任务。`Task`类提供了更简洁的API,简化了异步编程和并行处理。 在实践中,通过分析任务的性质和系统资源...