Java学习_多线程
来源:互联网 发布:java读取csv文件内容 编辑:程序博客网 时间:2024/06/11 20:52
线程安全
在代码所在的进程中有多个线程同时在执行,这些进程都会使用这段代码,在执行的过程中,每次的运行结果和单线程运行时的结果是一致的,而且其他变量的值和预期也是一样的,则是线程安全的。
线程安全是由全局变量和静态变量引起的,若多个线程对同一个变量进行写操作,就要考虑线程同步的问题。
多线程可以将一个程序划分为多个任务,彼此独立工作,方便有效地使用处理器和用户时间。多线程的两种创建方式
1)、自己重写一个线程类继承 java.lang.Thread 类。
2、直接实现 Runnable 接口来重写 run()方法实现线程。几种方法的区别
1)、 sleep()方法是Thread类(线程类)的方法,使当前线程暂停执行指定的时间,把执行机会让给其他线程,但不会释放对象锁,在时间到了之后会自动恢复。
2)、 wait()方法是Object类的方法,当前线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法后本线程才进入对象锁定池准备获得对象锁进入运行状态。
3)、 yield()方法只是让出自己的CPU时间片,并且立即进入Runnable状态参与CPU时间竞争,而sleep()进入blocked状态,等时间结束之后才进入Runnable状态参与竞争CPU时间片。volatile关键字的作用
1)、保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这个新值对其他线程是立即可见的。
2)、禁止指令重新排序。volatile和synchronize关键字比较
1)volatile关键字告诉jvm这个值是不确定的,需要从主存中读取;
synchronize则是锁定当前变量,只有当前线程可以访问这个变量,其他线程访问这个变量是会被阻塞的。
2)volatile关键字只能用在变量级;
synchronize则可以用在变量,方法,类级别。
3)volatile只能保证变量的修改可见性,不能保证原子性;
synchronize不仅可以保证修改可见性,还可以保证原子性。
4)volatile不会造成线程阻塞;
synchronize会造成线程阻塞。
5)volatile标记的标量不会被编译器优化;实现同步的方法
实现同步的方式为使用synchronize关键字
1)同步方法:可以使静态或非静态方法,不能是抽象方法或者接口方法,当一个线程调用这个对象的同步方法时,则这个对象的所有同步方法都被锁定,不能被访问,单可以调用这个类的非同步方法。
2)同步块:锁定一个指定的对象,来对同步块中的代码进行同步。synchronize和Java.util.concurrent.locks.lock的区别
相同:lock和synchronize都实现了线程同步;
不同:lock比synchronize有更准确的线程语义和更好的性能,synchronize对自动释放锁,而lock需要程序员手动释放锁,并且必须在finally中释放。多线程的数据存储
在 java 的内存模型中每一个线程运行时都有一个线程栈,线程栈保存了线程运行时候变量值信息。当线程访问某一个对象值得时候,首先通过对象的引用找到对应在堆内存的变量的值,然后把堆内存变量的具体值 load 到线 程本地内存中,建立一个变量副本,之后线程就不再和对象在堆内存变量值有任何关系,而是直接修改副本变量的值, 在修改完之后的某一个时刻(线程退出之前),自动把线程变量副本的值回写到对象在堆中变量。这样在堆中的对象 的值就产生变化了。所以当有多个线程对同一个变量进行修改的时候,每一个线程都会有一个变量副本,每个线程修改变量只是临时修改了 自己的副本,当线程结束时再将修改的值写入在主内存中,这样就出现了线程安全问题。线程池
当一个程序在执行的时候若创建大量线程,并在任务结束的时候销毁会造成大量的系统开销,以及过度切换线程的危险,从而导致系统崩溃。
线程池就是事先将多个线程放到某一个容器中,容器就是线程池。在用户需要使用线程时,不是new一个线程出来,而是在线程池中取出一个空闲的线程为之服务,服务结束之后不结束线程,而是将这个线程放回到线程池中,供下次需要的时候从线程池中取出使用。一个线程只能同时执行一个任务,但可向一个线程池提交多个任务。
在 JDK 的 java.util.concurrent.Executors 中提供了生成多种线程池的静态方法。e
ExecutorService newCachedThreadPool = Executors.newCachedThreadPool(); ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(4); ScheduledExecutorService newScheduledThreadPool = Executors.newScheduledThreadPool(4);ExecutorService newSingleThreadExecutor = Executors.newSingleThreadExecutor();
然后调用他们的execute方法即可。
- Java学习_多线程
- java学习_多线程1
- java学习[1]_多线程
- java基础学习笔记_多线程
- 黑马程序员_ JAVA学习日记—JAVA中的多线程
- C++学习_多线程
- python学习_多线程
- 学习笔记_多线程
- Java基础_多线程
- Java复习_多线程
- Java研究_多线程
- Java基础_多线程
- java基础_多线程
- Java入门_多线程
- Java多线程_基础
- 学习笔记7—Java基础5_多线程
- 黑马程序员--Java学习日记6_多线程
- Java基础学习4_多线程(同步)
- 第4周项目5-用递归方法求解4
- CF_5A_ChatServer'sOutgoingTraffic
- HDOJ 2049 不容易系列之(4)——考新郎
- 开发者需要知道的iOS 8 SDK新特性
- 关于String,StringBuffer与StringBuilder
- Java学习_多线程
- IOS学习之——面试问题集锦
- 三角形三边
- 深入理解ThreadLocal
- iOS 7 新特性:视图控制器切换API
- Django + Apache + wsgi配置和环境搭建(ubuntu)
- hdu 1874 畅通工程续 最短路spfa
- App 被拒原因
- HTML+CSS基础篇(四)——编码规范