Java线程同步与多线程

 

20120408

交通灯、银行项目都涉及到了多线程。先搞懂线程里大概的知识点吧。
一、进程与线程
首先就是进程与线程的区别。我们在操作系统中运行一个程序,都会在系统建立一个进程(任务管理器的exe),而在这个进程中,就至少有一个线程在运行,它叫做主线程,也是这个程序运行的入口点,感觉就像一个java工程的含有main主程序(入口点)的那个java程序一样。线程也是程序运行时的基本执行单元。在操作系统中可以有多个进程,包括系统进程和用户进程,一个进程中又可以有一个或多个线程。进程和进程之间不共享内存,都是在各自独立的内存空间中运行,内存独占吧。但一个进程中的线程可以共享系统分配给这个进程的内存空间。线程不仅可以共享进程的内存,而且还拥有一个属于自己的内存空间,这段内存空间也叫做线程栈, 是在建立线程时由系统分配的,主要用来保存线程内部所使用的数据,如线程执行函数中所定义的变量。

在操作系统将进程分成多个线程后,这些线程可以再操作系统的管理下并发执行,从而大大提高了程序的运行效率。但一块CPU同时只能执行一条指令,所以操作系统实际上是在执行多个线程的过程中,在一个线程空闲时将其撤下,并去执行另一个线程。这叫做线程调度。只不过互相切换的时间短(几毫秒级),所以看上去像是多个线程在同时执行。

二、java线程的同步与异步、线程池

1、多线程并发执行时,有可能同时请求同一个资源,所以有可能线程A修改了B线程的数据,而B线程又修改了A线程的数据,这样会造成数据的不安全。这又是由于全局资源造成的,有时为了解决这个问题,优先考虑使用局部变量,使用同步代码块,出于这样的安全考虑就必须牺牲系统处理性能,加在多线程并发时资源挣夺最激烈的地方,这就实现了线程的同步机制。
同步:A线程要请求某个资源,但是此资源正在被B线程使用中,因为同步机制存在,A线程请求不到,怎么办,A线程只能等待下去
异步:A线程要请求某个资源,但是此资源正在被B线程使用中,因为没有同步机制存在,A线程仍然请求的到,A线程无需等待。

显然,同步是最安全,最保险的。而异步不安全,容易导致死锁,这样一个线程死掉就会导致整个进程崩溃,但没有同步机制的存在,性能会有所提升。

说白了就是当多个线程同时访问同一个资源的时候,为了保证数据的安全,避免读脏数据,就要给对这个资源的访问加锁,就是synchronized(互斥),即同时只能有一个线程去访问数据,当访问完毕后解锁,其他线程才能去访问。用张孝祥老师的话讲就是,当两个线程同时访问一个相同的数据,会出问题,所以要实现互斥,就是加上synchronized。synchronized用于多线程设计,有了synchronized关键字,多线程程序的运行结果将变得可以控制。synchronized关键字用于保护共享数据,它依靠"锁"机制进行多线程同步,"锁"有2种,一种是对象锁,一种是类锁。
它可以修饰的对象有:
1)synchronized{static方法 or 普通方法} 函数的修饰符, 就是同步方法.
2)synchronized{修饰代码块} 可作为函数内语句的修饰符, 就是同步语句块
3)synchronized{对象引用} 注意对象必须是线程安全的.(比如: StringBuffer在JDK1.5中是线程安全的, 而数组, ArrayList是不安全的)

三、交通灯、银行项目里都用到的Executors类的方法创建线程池

Executors类提供了一系列工厂方法用于创先线程池,返回的线程池都实现了ExecutorService接口。
1)newFixedThreadPool
public static ExecutorService newFixedThreadPool(int nThreads);
public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory);

创建一个可重用固定线程集合的线程池,以共享的无界队列方式来运行这些线程。如果在关闭前的执行期间由于失败而导致任何线程终止,那么一个新线程将代替它执行后续的任务(如果需要)。
2)newSingleThreadExecutor
public static ExecutorService newSingleThreadExecutor();
public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory);

创建一个使用单个 worker 线程的 Executor,以无界队列方式来运行该线程。(注意,如果因为在关闭前的执行期间出现失败而终止了此单个线程,那么如果需要,一个新线程将代替它执行后续的任务)。可保证顺序地执行各个任务,并且在任意给定的时间不会有多个线程是活动的。与其他等效的 newFixedThreadPool(1) 不同,可保证无需重新配置此方法所返回的执行程序即可使用其他的线程。
3)newCachedThreadPool
public static ExecutorService newCachedThreadPool();
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory);

创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们。对于执行很多短期异步任务的程序而言,这些线程池通常可提高程序性能。调用 execute 将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。因此,长时间保持空闲的线程池不会使用任何资源。注意,可以使用 ThreadPoolExecutor 构造方法创建具有类似属性但细节不同(例如超时参数)的线程池。
4)newScheduledThreadPool
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize);
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory);

创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行,就像张孝祥老师所说的“定时炸弹”!!
5)newSingleThreadScheduledExecutor
public static ScheduledExecutorService newSingleThreadScheduledExecutor();
public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory);

创建一个单线程执行程序,它可安排在给定延迟后运行命令或者定期地执行。(注意,如果因为在关闭前的执行期间出现失败而终止了此单个线程,那么如果需要,一个新线程会代替它执行后续的任务)。可保证顺序地执行各个任务,并且在任意给定的时间不会有多个线程是活动的。与其他等效的 newScheduledThreadPool(1) 不同,可保证无需重新配置此方法所返回的执行程序即可使用其他的线程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哪知道

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值