`

多线程总结(转)

 
阅读更多
多线程:
	线程是进程中的一个控制单元。
	一个进程至少有一个线程,为了提高效率,可以在一个进程中开启多个控制单元。
	并发运行。如:多线程下载软件。
	
	可以完成同时运行,但是通过程序运行的结果发现,虽然同时运行,但是每一次结果都不一致。


	因为多线程存在一个特性:随机性。
	造成的原因:CPU在瞬间不断切换去处理各个线程导致的。
	可以理解成多个线程在抢cpu资源。

	如果在程序中创建一个新的控制单元呢?

	Java对线程有自己描述,而且在调用系统资源。
	该描述的类是Thread。只要创建Thread类的对象即可在内存中建立新的控制单元。

	但是创建线程的目的是为了运行自定义的代码。
	自定义的代码如何和多线程相结合呢?
	通过start方法明确,线程是在执行run方法。
	那么只要将线程需要运行的代码存入到run方法中即可。
	只要继承Thread类并复写该run方法即可。

	创建线程的第一种方式:继承Thread类;
	1,定义Thread类的子类。创建子类对象,就是在内存中建立了控制单元。
	2,复写Thread类中的run方法。将多线程要运行的代码存入其中。
	3,调用线程Thread中的start方法开启线程,并让jvm运行run方法。

	线程的四种状态:
	1,被创建.new Thread类或者Thread类的子类对象。
	2,通过start方法,让线程进入到了运行状态。
	3,线程存活的情况,可以不运行,因为到了冻结状态。
	4,消亡,线程执行的代码结束。

	如何获取当前线程对象呢?
	通过Thread类中的静态方法:Thread currentThread()。
	获取线程的名称 getName():默认是Thread-编号。

	class Demo extends Thread
	{
		public void run()
		{
			for(int x=0; x<20; x++)
			{
				System.out.println(Thread.currentThread().getName());
			}
		}
	}

	main()
	{
		Demo d1 = new Demo();
		Demo d2 = new Demo();
		//d1.run();
		//d2.run();当直接对象调用run方法,其实是一共有三个线程,
			//但是只有主线程在运行。所以打印的都是主线程的名称main。
		d1.start();
		d2.start();//有三个线程,并三个线程都处于运行状态,在互相抢资源运行。


		for(int x=0; x<30; x++)
		{
			System.out.println(Thread.currentThread().getName());
		}
	}

	class Ticket extends Thread
	{
		private int num = 100;
		public void run()
		{
			while(true)
			{
				if(num>0)
				{
					System.out.println(Thread.currentThread().getName()+"..."+num--);
				}
			}
		}
	}
	main()
	{
		Ticket t1 = new Ticket();
		Ticket t2 = new Ticket();
		Ticket t3 = new Ticket();
		Ticket t4 = new Ticket();
		t1.start();
		t2.start();
		t3.start();
		t4.start();

		//结果是将票进行打印,但是出现了400张票。
		因为每一个ticket对象中都有自己的num。
		可以通过将num修饰成static的,这是可以的,但是通常不建议定义static因为生存周期过长。


		Ticket t1 = new Ticket();
		
		t1.start();
		t1.start();
		t1.start();
		t1.start();

		//一个线程开启多次,会造成无效的线程状态异常。IllegalThreadStateException


	}


	什么时候需要多线程呢?
	当多部分代码需要同时运行时,就需要使用多线程技术。
	聊天软件的例子。发送区域和接收数据区域就是同时运行的。

------------------------------------

两种创建方式:
	1,继承Thread类。复写run方法,通过start方法开启线程。并让jvm调用run方法。
	2,实现Runnable接口;
		2.1定义类实现Runnable接口。
		2.2复写接口中run方法。
		2.3通过Thread类建立线程对象。
		2.4将实现了Runnable接口的子类对象作为参数传递给Thread类的构造函数。
			目的:让线程可以执行执行的接口子类的run方法。
		2.5调用Thread类的start方法开启线程。
	
	这两种方式区别:
	线程代码存放的位置不同,一个存放在Thread类的子类中。一个存在Runnable接口的子类中。

	第二种方式有什么好处呢?
	1,将资源对多线程共享。
	2,避免了单继承的局限性。
		
	-----------------
	线程的安全问题。
	造成的原因是什么?
	多条语句同时操作通一个成员变量,这些语句被多个线程分开执行会造成成员数据的错误。
	int num = 100;
	public void run()
	{
		while(true)
		{
			if(num>0)
				-->0  -->1
				System.out.println(num--);
		}
	}


	如何解决呢?
	可以通过同步的方式解决线程安全问题。
	原理:
	将出现安全问题的语句存放同步区域中,同步区域的好处在于给该区域加锁。
	这样就保证了某一时刻只有一个线程在同步区域内执行多条语句。

	弊端:消耗资源,对效率有降低。

	如果同步嵌套,容易出现死锁。

	在书写同步的时候前提:
	1,需要两个或者两个以上的线程。
	2,多个线程必须使用同一个锁。

	同通过一个比喻理解同步:火车上的卫生间。

	同步有两种表现形式:
	1,同步代码块:一个单独的封装区域。通过同步关键字定义的。锁是自定义的任意对象。
	2,同步函数:将同步关键字作为修饰符定义在函数上,让函数具备了同步的特性,使用的锁this。
		特例:静态同步函数使用的是什么锁呢?字节码文件所属对象。类名.class.

	单例设计模式的中的懒汉式设计模式的特点:
	class Single
	{
		private static  Single s = null;
		private Single(){}
		public static Single getInstance()
		{
			if(s == null)
				
				s = new Single();
			return s;
		}
	}
	这种懒汉式当多线程并发访问该方法时,会出现线程安全问题。

	if(s == null)
		-->0  -->1		
		s = new Single();
	为了解决这个问题,将这个方法修饰为同步的。
	public static synchronized Single getInstance()
	{
		if(s == null)			
			s = new Single();
		return s;
	}

	这是修饰虽然解决了安全问题,但是效率较低。因为每一个线程访问该方法时,都要判断Single.class这个锁。

	优化一下。通过双重判断的形式。
	public static  Single getInstance()
	{
		if(s==null)
		{
			--.0 --.1
			synchronized(Single.class)
			{
				if(s == null)			
					s = new Single();
			}
		}
		return s;
	}
		
	---------
	线程间的通信。
	多个线程在操作同一个资源。但是操作的动作不一致。
	需要对这个动作分别进行描述,并存放在不同的run方法。

	通常可以可以将资源作为参数传递给run方法做在类的构造函数。

	wait(),notify(),notifyAll().也可以通过比喻:儿时的抓人游戏。
	
	notify():唤醒的是线程池中的第一个。

	这些方法都使用在同步中。
	用于操作线程。

	这些方法为什么定义在了Object类中?
	因为这三个方法,需要标识线程所属的锁。lock.wait(),lock.notify();
	而锁可以是任意对象,那么任意对象可以调用的方法定义在Object类中。

	wait(),sleep()的特点:
	wait():释放资源,释放锁。
	sleep():释放资源,不释放锁。

	-------------------------

	线程的停止:
	因为stop方法过时了。
	所以只有一方式:run方法结束。
	run方法中通常都会定义循环。
	1,定义结束标记。只要控制住循环,就可以结束run方法。
	但是这种情况也有局限:当线程处于了冻结状态,是不会执行标记的。
	2,interrupt():强制将冻结状态清除,让线程从冻结状态转回运行状态,就有机会执行到标记。
			但这种方式会发生异常。InterruptedException.
			可以作用于被wait,sleep,join、方法冻结的线程。
	
	
	-------------------------
	setPriority(int):设置线程的优先级。级别:1~10.
			有三个常量可用。MIN_PRIORITY=1,MAX_PRIORITY=10,NORM_PRIORITY=5
			所有线程默认是都是5。
	
	setDaemon(boolean):将线程标记成守护线程。
				有什么特点呢?当前台线程都结束后,守护线程自动结束。
				注意:必须要用的线程开启前。
	
	join():加入线程。当某一个线程A在执行时,执行到了B.join().那么A会释放出资源,
			等待B线程运行结束,A在恢复到运行状态。

	static void yield():让线程临时暂停,时间较短,只为延缓线程的速度。


	聊天程序使用了多线程技术。

	web服务器也使用了多线程技术。
	将每一个访问web服务端的客户端封装成一个线程。可以让多个客户端并发访问服务器。
		
	对于已有的服务端软件,如Tomcat。内部就封装了多线程技术。

转自:http://caiwb1990.iteye.com/blog/1401631---------------------------------------------


 

分享到:
评论

相关推荐

    java多线程编程总结

    详细的讲述了多线程的各种用法 Java线程:概念与原理 Java线程:创建与启动 Java线程:线程栈模型与线程的变量 Java线程:线程状态的转换 Java线程:线程的同步与锁 Java线程:线程的交互 Java线程:线程的调度-休眠...

    Java多线程编程总结

    Java 线程系列博文总结word化,编目如下,欢迎互相学习交流: Java线程:概念与原理 Java线程:创建与启动 Java线程:线程栈模型与线程的变量 Java线程:线程状态的转换 Java线程:线程的同步与锁 Java线程:...

    C# 多线程总结

    C# 多线程总结,比较详细和全面,包含多种方式的多线程方法的说明。

    转多线程总结资料

    二、Java与多线程 Java语言的多线程需要操作系统的支持。 Java 虚拟机允许应用程序并发地运行多个执行线程。Java语言提供了多线程编程的扩展点,并给出了功能强大的线程控制API。 在Java中,多线程的实现有两...

    springboot 文件转换PDF多线程

    根据网上的资料总结的一个springboot 转换pdf Word文档大小最好2m以下 需要安装OpenOffice.org 3.3 链接:https://pan.baidu.com/s/1onrkhBCNlGLEmf3hPwzXWw 密码:8h5a

    【2018最新最详细】并发多线程教程

    【2018最新最详细】并发多线程教程,课程结构如下 1.并发编程的优缺点 2.线程的状态转换以及基本操作 3.java内存模型以及happens-before规则 4.彻底理解synchronized 5.彻底理解volatile 6.你以为你真的了解final吗...

    ThreadLocal:如何优雅的解决SimpleDateFormat多线程安全问题

    目录SimpleDateFormat诡异bug复现SimpleDateFormat诡异bug字符串日期转Date日期(parse)Date日期转String类型(format)SimpleDateFormat出现bug的原因如何解决SimpleDateFormat多线程安全问题局部变量使用...

    Linux多线程服务端编程:使用muduo C++网络库

    《Linux多线程服务端编程:使用muduo C++网络库》主要讲述采用现代C++在x86-64 Linux上编写多线程TCP网络服务程序的主流常规技术,重点讲解一种适应性较强的多线程服务器的编程模型,即one loop per thread。...

    java线程详解

    Java线程:概念与原理 Java线程:创建与启动 Java线程:线程状态的转换 Java线程:线程的同步与锁 一、同步问题提出 二、同步和锁定 三、静态方法同步 四、如果线程不能不能获得锁会怎么样 ...Java线程:大总结

    java基础总结.xmind

    IO、面向对象Object类、API、集合体系、IO体系、面向对象、多线程、递归、相互转换、正则表达式

    Java基础知识点总结.docx

    十二、 多线程★★★★ 39 为什么要使用多线程 39 创建线程和启动 39 线程的生命周期 44 线程管理 45 线程同步 49 线程通信 52 线程池 58 死锁 64 线程相关类 65 十三、 同步★★★★★ 67 十四、 Lock接口 70 十五...

    java数据分析源码-javaModel:java高级基础知识总结,算法,数据结构,多线程,jvm优化,spring源码分析,java新特性等

    一、多线程高并发(concurrent、jvm包) 1.JUC多线程及高并发 1.1 多线程集合 1.2 cas 1.3 锁 1.4 队列 1.5 线程池 2.JVM+GC解析 demo 二、JDK8新特性(lamp包) 1.四大函数式接口 2.方法引用 3.构造器引用 4.数组...

    C++转JAVA入门总结

    1. 内置数据类型 2. string类 3. 数组 4. 循环分支 5. 工具类(数据容器、日期、正则表达式……) 6. JAVA流、文件、IO 7. JAVA异常 8. JAVA继承 1. 抽象类与抽象方法 ...5.JAVA网络与多线程 6. JAVA类生命周期

    linux系统编程之线程.zip

    【练习】:编写多线程程序,总结exit、return、pthread_exit各自退出效果。 return:返回到调用者那里去。 pthread_exit():将调用该函数的线程 exit: 将进程退出。 pthread_join函数 阻塞等待线程退出,获取...

    JavaSE 五万字总结.pdf

    Java基础语法 类型转换 运算符 流程控制 循环 Random 数组 方法 方法重载 递归 二进制 类和对象 成员变量局和部变量 封装 构造方法 String 集合 继承 GIT 抽象类 多态 Java8 异常 泛型 Map File IO 多线程 线程池 ...

    C++ 线程(串行 并行 同步 异步)详解

    看了很多关于这类的文章,一直没有总结。不总结的话就会一直糊里糊涂,以下描述都是自己理解的非官方语言,不一定严谨,可当作参考。 首先,进程可理解成一个可执行文件的执行过程。在ios app上的话我们可以理解为...

    Java编码规范总结

    4.多线程错误 - 错误的延迟初始化和更新静态属性。 5.错误用法 - 集合转换为数组元素时发生的类型转换错误。 修复建议:使用c.toArray(new String[c.size()])。 6.不良实践 - 方法返回boolean类型返回了null。 ...

Global site tag (gtag.js) - Google Analytics