多线程

java内存模型与多线程

我们两清 提交于 2020-03-30 12:48:42
现代计算机,cpu在计算的时候,并不总是从内存读取数据,它的数据读取顺序优先级是:寄存器-高速缓存-内存,线程计算的时候,原始的数据来自内存,在 计算过程中,有些数据可能被频繁读取,这些数据被存储在寄存器和高速缓存中,当线程计算完后,这些缓存的数据在适当的时候应该写回内存,当多个线程同时读 写某个内存数据时,由于涉及数据的可见性、操作的有序性,所以就会产生多线程并发问题。 Java作为平台无关性语言,JLS(Java语言规范)定义了一个统一的内存管理模型 JMM (Java Memory Model),JMM屏蔽了底层平台内存管理细节,在多线程环境中必须解决可见性和有序性的问题。JMM规定了jvm有 主内存 (Main Memory)和 工作内存 (Working Memory) ,主内存存放程序中所有的类实例、静态数据等变量,是多个线程共享的,而工作内存存放的是该线程从主内存中拷贝过来的变量以及访问方法所取得的局部变量, 是每个线程私有的其他线程不能访问,每个线程对变量的操作都是以先从主内存将其拷贝到工作内存再对其进行操作的方式进行,多个线程之间不能直接互相传递数 据通信,只能通过共享变量来进行。 JLS定义了线程对主存的操作指令: read,load,use,assign,store,write 。这些行为是不可分解的原子操作,在使用上相互依赖,read

Java多线程中static变量的使用

老子叫甜甜 提交于 2020-03-30 11:44:35
线程,是我们项目中绕不过的重点领域。提到线程,就常会听到线程安全的术语。那什么是线程安全呢?通俗点说,就是线程访问时不产生资源冲突。其实,这是一个有点难以定义的概念,不是很容易让人一听就懂的概念。“一个类可以被多个线程安全调用就是线程安全的”《 Java 并发编程实践》。 来说说静态变量、实例变量、局部变量在多线程下的安全问题吧! (一)静态变量:线程非安全 1、静态变量:使用static关键字定义的变量。static可以修饰变量和方法,也有static静态代码块。被static修饰的成员变量和成员方法独立于该类的任何对象。也就是说,它不依赖类特定的实例,被 类的所有实例共享 。只要这个类被加载,Java虚拟机就能根据类名在运行时数据区的方法区内定找到他们。因此,static对象可以在它的任何对象创建之前访问,无需引用任何对象。 用public修饰的static成员变量和成员方法本质是 全局 变量和全局方法,当声明它的类的对象时,不生成static变量的副本,而是类的所有实例共享同一个static变量。 2、静态变量使用的场景: (1)对象间共享值时 (2)方便访问变量时 3、静态方法使用注意事项: (1)不能在静态方法内使用非静态变量,即不能直接访问所属类的实例变量; (2)不能在静态方法内直接调用非静态方法; (3)静态方法中不能使用this和super关键字; 4

Delphi管理多线程之线程局部存储:threadvar

拜拜、爱过 提交于 2020-03-30 11:43:47
  尽管多线程能够解决许多问题,但是同时它又给我们带来了很多的问题。其中主要的问题就是:对全局变量或句柄这样的全局资源如何访问?另外,当必须确保一个线程中的某些事件要在另一个线程中的其他时间之前(或之后)发生时,该怎么办?这里将讲解通过使用由 Delphi提供的线程局部存储和 A P I为线程提供同步的方法。   这里先讲线程局部存储,下一篇再讲线程同步 线程局部存储   由于每个线程都代表一个不同的执行路径,因此,最好有一种只限于一个线程内部使用的数据存储方式。要实现上述目的有三种方式: 1) 第一种也是最简单的一种方式是局部变量((基于栈)。   由于每个线程都在各自的栈中,各个线程都将有一套局部变量的副本,这样,就不会互相影响。 2)第二种方式就是把有关信息保存在各自的线程对象中 3)第三种方式就是用Delphi的关键字 threadvar 来声明变量,以利用操作系统级的线程局部存储 1.把信息保存在TThread派生对象中   将相关信息保存在TThread派生对象中,这是一种线程局部存储可选的技术。相对于使用关键字threadvar的技术,这种方式更加简单、更加有效。例如,你可以在一个线程对象中加入下列信息 type TMyThread = class(TThread) private FLocalInt: Integer; FLocalStr: String; .. .

java基础第十六篇之多线程

别说谁变了你拦得住时间么 提交于 2020-03-30 05:44:49
1:线程的概念 进程(任务):一个正在运行的程序 进程的调度:CPU来决定什么时候该运行哪个进程 (时间片轮流法) 线程在一个应用程序中,同时,有多个不同的执行路径,是进程中的实际运作单位。 好处是提高程序效率。 1.2 线程和进程的关系 a:一个进程可以创建多个线程 b:线程必须依赖于进程而存在 c:多个线程共享进程的空间 d:进程和线程得到CPU的机会是均等的‘ 1.3 为什么要搞多线程 我们可以让程序同时执行(并发执行) //Java只让我们创建线程,而不让我们创建进程 HelloWorld.java javac HelloWorld.java java HelloWorld --->JVM 启动进程 Run Application --->JVM 启动进程 //一个进程中至少要有一个线程 main方法 被称为 主线程 2: 线程的创建方式 Thread 类 方式1:继承Thread类 1:自定义一个类,继承Thread类 2:重写Thread类的run方法 3:创建自定义类对象 4:让自定义类对象调用start方法,启动线程 例题: package pack01_thread; public class Demo01Thread { public static void main(String[] args) { //3:创建自定义类对象 MyThread mt = new

多线程和同步

拜拜、爱过 提交于 2020-03-29 13:06:59
先说一下什么是多线程 个人理解: 让几个方法同时执行(以极快速的在几个方法中切换)就是多线程 实现多线程的方法 1 继承thread类 重写run()方法   (1)如代码所示 public class A extends Thread{ public void run() { } }   (2)在主方法中创建A类的对象 A a1 = new A("一号窗口");   (3)调用a1对象的start方法 a1.start(); 2实现runnable接口 1 实现接口 public class B implements Runnable { //总票数 private static int railway=30; @Override public void run() { // TODO Auto-generated method stub while(true) { if(railway>0){ try { Thread.sleep(50); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"卖了第"+railway--+"张火车票");

多线程同步中的门道(二)

纵然是瞬间 提交于 2020-03-29 13:01:14
多线程同步中的门道(二) 前言   在涉及到多线程的开发时,线程同步的考虑是不可缺少的,否则很可能会造成各种超出预料的错误结果。以自己的学习经历来说,对于刚开始接触线程同步的人可能会感觉非常简单,在多线程操作可能会造成数据混乱的地方同步一下不就行了嘛,加个synchronized关键字,多简单!可是随着开发的深入,会渐渐的发现仅仅是一个synchronized关键字也不是那么简单,里面的门道和考虑到的情况还是不少。本系列就着循序渐进的程序和大家探讨一下synchronized关键字使用中的各种情形和会造成的各种意料之外和意料之中的结果,欢迎各位大神轻拍。 转载请注明本文地址: http://www.cnblogs.com/hellojava/p/3635336.html 系列文章: 多线程同步中的门道(一)   synchronized涉及到同步方法、同步代码块、同步类、同步对象、静态方法等,本系列来挨个探讨。   注:因为考虑到文章篇幅和为了突出我们要分析的关键代码,所以下面程序有可能不会是最优写法。 同步代码块   同步代码块,分为同步对象和同步类两种,下面我们来挨个介绍。 同步对象   我们首先来看看一个同步对象的例子。   [测试程序4.1] /** * Test case 4.1. synchronized code block.synchronized object.

Java回顾之多线程同步

这一生的挚爱 提交于 2020-03-29 12:48:23
在这篇文章里,我们关注线程同步的话题。这是比多线程更复杂,稍不留意,我们就会“掉到坑里”,而且和单线程程序不同,多线程的错误是否每次都出现,也是不固定的,这给调试也带来了很大的挑战。   在这篇文章里,我们首先阐述什么是同步,不同步有什么问题,然后讨论可以采取哪些措施控制同步,接下来我们会仿照回顾网络通信时那样,构建一个服务器端的“线程池”,JDK为我们提供了一个很大的concurrent工具包,最后我们会对里面的内容进行探索。   为什么要线程同步?   说到线程同步,大部分情况下, 我们是在针对“ 单对象多线程 ”的情况进行讨论,一般会将其分成两部分,一部分是关于“共享变量”,一部分关于“执行步骤”。   共享变量   当我们在线程对象(Runnable)中定义了全局变量,run方法会修改该变量时,如果有多个线程同时使用该线程对象,那么就会造成全局变量的值被同时修改,造成错误。我们来看下面的代码: 1 class MyRunner implements Runnable 2 { 3 public int sum = 0; 4 5 public void run() 6 { 7 System.out.println(Thread.currentThread().getName() + " Start."); 8 for (int i = 1; i <= 100; i++) 9 {

线程池

对着背影说爱祢 提交于 2020-03-29 12:18:37
线程,是程序执行的最小单元。一个标准的线程由线程ID,当前指令指针,寄存器集合和堆栈组成。另外,线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。以上概念来自于百度百科。对于开发者来说,线程就是帮我们干实事的伙伴。在Java中,对于线程的基本操作,我们知道在代码中有以下三种写法: (1)自定义一个类,去继承Thread类,重写run方法 (2)自定义一个类,去实现Runnable接口,重写run方法 (3)自定义一个类,实现Callable接口,重写call方法。关于这个Callable,要多提一嘴,首先,Callable规定的方法是call(),而Runnable规定的方法是run().;其次,Callable的任务执行后可返回值,而Runnable的任务是不能返回值的;然后,call()方法可抛出异常,而run()方法是不能抛出异常的;最后,运行Callable任务可拿到一个Future对象。 实现Callable接口 因为线程的基本概念和使用大家基本上都很熟悉,所以这里就点到为止。 关于线程,就不得不提及另外一个经常容易被混淆的概念,那就是并行和并发。 关于并行和并发

任务并发执行是一个宏观概念,微观上是串行的。

若如初见. 提交于 2020-03-29 12:18:02
多线程 进程:任务 任务并发执行是一个宏观概念,微观上是串行的。 进程的调度是有OS负责的(有的系统为独占式,有的系统为共享式,根据重要性,进程有优先级)。 由OS将时间分为若干个时间片。 JAVA 在语言级支持多线程。 分配时间的仍然是OS。 参看P377 线程由两种实现方式: 第一种方式: class MyThread extends Thread{ public void run(){ 需要进行执行的代码,如循环。 } } public class TestThread{ main(){ Thread t1=new Mythread(); T1.start(); } } 只有等到所有的线程全部结束之后,进程才退出。 来源: https://www.cnblogs.com/borter/p/10744102.html

十三、多线程

情到浓时终转凉″ 提交于 2020-03-29 12:02:14
1、实现线程的两种方式 (1)继承Thread类   Thread构造方法:public Thread(String threadName)            public Tread()   重写run()方法,并调用start()执行线程。   语法:public static void main(String [] args){         new ThreadTest().start();       } (2)实现Runnable接口   语法:public class Thread extends Object implements Runnable   实现Runnable接口会创建Thread对象,并将Runnable对象和Thread对象相关联。   Thread构造方法:public Thread(Runnable r)            public Thread(Runnable r,String name)   步骤:1)建立Runnable对象      2)使用参数为Runnable对象的构造方法创建Thread实例。      3)调用start()方法启动线程。   创建Runnable对象:编写一个实现Runnable接口的类,然后实例化该类的对象。 2、线程的生命周期 (1)出生状态:调用start()前 (2)就绪状态