Java学习_多线程
2016-03-30 20:08
513 查看
线程安全
在代码所在的进程中有多个线程同时在执行,这些进程都会使用这段代码,在执行的过程中,每次的运行结果和单线程运行时的结果是一致的,而且其他变量的值和预期也是一样的,则是线程安全的。
线程安全是由全局变量和静态变量引起的,若多个线程对同一个变量进行写操作,就要考虑线程同步的问题。
多线程可以将一个程序划分为多个任务,彼此独立工作,方便有效地使用处理器和用户时间。
多线程的两种创建方式
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
然后调用他们的execute方法即可。
在代码所在的进程中有多个线程同时在执行,这些进程都会使用这段代码,在执行的过程中,每次的运行结果和单线程运行时的结果是一致的,而且其他变量的值和预期也是一样的,则是线程安全的。
线程安全是由全局变量和静态变量引起的,若多个线程对同一个变量进行写操作,就要考虑线程同步的问题。
多线程可以将一个程序划分为多个任务,彼此独立工作,方便有效地使用处理器和用户时间。
多线程的两种创建方式
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对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- Python3写爬虫(四)多线程实现数据爬取
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序