文档章节

JAVA学习日志(11-1-线程及多线程概述)

Almon
 Almon
发布于 2016/08/12 15:46
字数 1206
阅读 7
收藏 1

进程:一个正在执行中的程序,每一个进程执行都有一个执行顺序

            该顺序就是一个执行路径/控制单元

线程:进程中的一个独立控制单元,控制着进程的执行

            一个进程中至少有一个线程

    eg.Java VM启动时会有一个进程java.exe

        该进程中至少有一个线程负责java程序的执行,而且这个线程运行的代码存在于

        main方法中,该线程成为主线程

        扩展:jvm启动不止一个线程,还有负责垃圾回收机制的线程

如何定义一个线程:Java-API-Thread类-继承Thread类

/* 
	1.定义类继承Thread
	2.复写Thread中的run方法
	3.调用线程的start方法:启动线程,调用run方法
    **CPU并不是同时进行线程,而是在不同线程之间切换进行
 */
class Demo extends Thread{
	public void run(){
		System.out.println("Demo_Run");
	}
}
class ThreadDemo{
	public static void main(String[] args){
		Demo d=new Demo();
		d.start();
	}
}

多线程运行即互相抢夺CPU的执行权,即多线程的运行具有随机性

为什么要覆盖run方法?

    Thread用于描述线程,该类就定义了一个功能,用于存储线程要运行的代码,该储存

    功能就是run方法,即run用于储存线程要运行的代码

    覆写run()的目的在于储存自定义代码,让线程运行,

    **start()用于开启线程并执行run(),run()仅调用方法,创建线程,并未运行

线程的运行状态

    1.被创建

    2.运行    start()

    3.冻结:放弃执行资格    sleep(time) wait () notify()

    4.消亡    stop()

    **阻塞状态:等待cpu执行权,具备运行资格

获取线程对象及名称

    static Thread currentThread() 获取当前线程对象

    getName() 获取线程名称

    setName()/构造函数 设置线程名称

class Demo extends Thread{
	Demo(String name){
		super(name);
	}
	public void run(){
		for(int x=0;x<60;x++){
			System.out.println(Thread.currentThread()+this.getName()+"Demo_Run"+x);
		}
	}
}
class ThreadDemo{
	public static void main(String[] args){
		Demo d=new Demo("Mark_II");
		d.start();
		for(int x=0;x<60;x++){
			System.out.println("Demo"+x);
		}
	}
}

练习:卖票窗口

Ver 1.0

/* 
需求:简单的卖票程序
	多个窗口同时卖票
*/
class Ticket extends Thread{
	private static int tick=100; //用static 来共享总票数
	public void run(){
		while(true){
			if(tick>0){
				System.out.println(currentThread().getName()+"__"+"sale:"+tick--);
			}
		}
	}
}
class TicketDemo{
	public static void main(String[] args){
		Ticket t1=new Ticket();
		Ticket t2=new Ticket();
		Ticket t3=new Ticket();
		Ticket t4=new Ticket();
		t1.start();
		t2.start();
		t3.start();
		t4.start();
	}
}

V 2.0 解决共享票数的问题

/* 
需求:简单的卖票程序
	多个窗口同时卖票
*/
class Ticket implements Runnable{//extends Thread{
	private int tick=100;
	public void run(){
		while(true){
			if(tick>0){
				System.out.println(Thread.currentThread().getName()+"__"+ "sale:"+tick--);
			}
		}
	}
}
class TicketDemo{
	public static void main(String[] args){
		Ticket t=new Ticket();
		Thread t1=new Thread(t);
		Thread t2=new Thread(t);
		Thread t3=new Thread(t);
		Thread t4=new Thread(t);
		t1.start();
		t2.start();
		t3.start();
		t4.start();
	}
}
/* 创建线程的第二种方式:实现Runnable接口
	1.定义类实现Runnable接口
	2.覆盖Runnable接口中的run方法
		-将代码存放在该run方法中
	3.通过Thread类建立线程对象
	4.将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数
		-自定义的run方法所属对象是Runnable接口的子类对象
		 所以要让线程去指定对象的run方法,就必须明确该run方法的所属对象
	5.调用Thread类的start方法开启线程并调用Runnable接口子类的run方法 */

实现方式和继承方式的区别

    实现方式:避免了单继承的局限性,建议使用。

                      线程代码存放在接口子类的run()

    继承方式:线程代码存放在Thread的子类run()中

线程的安全问题

/*
    通过分析,发现打印出0,-1,-2等错票
    多线程的运行出现了安全问题

*/

class Ticket implements Runnable{//extends Thread{
	private int tick=100;
	public void run(){
		while(true){
			if(tick>0){
				try{Thread.sleep(10);}catch(Exception e){}
				System.out.println(Thread.currentThread().getName()+"__"+ "sale:"+tick--);
			}
		}
	}
}
class TicketDemo{
	public static void main(String[] args){
		Ticket t=new Ticket();
		Thread t1=new Thread(t);
		Thread t2=new Thread(t);
		Thread t3=new Thread(t);
		Thread t4=new Thread(t);
		t1.start();
		t2.start();
		t3.start();
		t4.start();
	}
}

问题的原因:
   当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分
   还没有执行完,另一个线程参与进来执行,导致了共享数据的错误
解决办法:
    对多条操作共享数据的语句,只能让一个线程执行完,其他线程不可以参与执行

    Java对于多线程的安全问题提供了专业的解决方式——同步代码块

synchronized(对象){
    需要同步的代码
}


class Ticket implements Runnable{//extends Thread{
	private int tick=400;
	Object obj=new Object();
	public void run(){
		while(true){
			synchronized(obj){
				if(tick>0){
					try{Thread.sleep(10);}catch(Exception e){}
					System.out.println(Thread.currentThread().getName()+"__"+ "sale:"+tick--);
				}
			}
		}
	}
}

 

© 著作权归作者所有

共有 人打赏支持
Almon
粉丝 2
博文 64
码字总数 44346
作品 0
江北
私信 提问
JAVA基础再回首(三十)——JAVA基础再回首完美结束,感概万千!

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/m366917/article/details/52724939 JAVA基础再回首(三十)——JAVA基础再回首完美结束,感概万千! 经过了几...

Aduroidpc
2016/10/02
0
0
java中高级大公司多线程面试题

1)在Java中Lock接口比synchronized块的优势是什么?你需要实现一个高效的缓存,它允许多个用户读,但只允许一个用户写,以此来保持它的完整性,你会怎样去实现它? lock接口在多线程和并发编...

java成功之路
10/30
0
0
Java面试需要准备哪些多线程并发的技术要点

一、概念 什么是线程 一个线程要执行任务,必须得有线程 一个进程(程序)的所有任务都在线程中执行的 一个线程执行任务是串行的,也就是说一个线程,同一时间内,只能执行一个任务 多线程原理 同一...

码蚁说架构
05/31
0
0
15个顶级Java多线程面试题及回答

Java 线程面试问题 在任何Java面试当中多线程和并发方面的问题都是必不可少的一部分。如果你想获得任何股票投资银行的前台资讯职位,那么你应该准备很多关于多线程的问题。在投资银行业务中多...

LCZ777
2014/05/27
0
0
【转】15个顶级Java多线程面试题及回答

Java 线程面试问题   在任何Java面试当中多线程和并发方面的问题都是必不可少的一部分。如果你想获得任何股票投资银行的前台资讯职位,那么你应该准备很多关于多线程的问题。在投资银行业务...

一只死笨死笨的猪
2014/09/30
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Caffe(二)-Python-自定义网络

这里我们用一个例子先来体验一下 首先定义一下我们的环境变量 $PYTHONPATH,我这儿是Windows开发环境,至于Windows Caffe怎么编译由读者自己下去搞定 我使用的控制台是 Windows PowerShell 添...

Pulsar-V
28分钟前
2
0
ActiveMQ从入门到精通(二)之可靠性机制

ActiveMQ的可靠性机制 缘由( 确认JMS消息) 只要消息被确认之后,才认为消息被成功消费了。消息的成功消费包括三个阶段:客户端接收消息、客户端处理消息以及客户端确认消息。在事务性会话中...

一看就喷亏的小猿
35分钟前
0
0
源码分析 Mybatis 的 foreach 为什么会出现性能问题

背景 最近在做一个类似于综合报表之类的东西,需要查询所有的记录(数据库记录有限制),大概有1W条记录,该报表需要三个表的数据,也就是根据这 1W 个 ID 去执行查询三次数据库,其中,有一...

TSMYK
今天
7
0
IC-CAD Methodology企业实战之openlava

在云计算解决安全问题并成为IC界主流运算平台之前,私有的服务器集群系统仍然是各大IC公司的计算资源平台首选。 现在主流的服务器集群管理系统包括lsf,openlava,SkyForm,三者都属于lsf一系...

李艳青1987
今天
5
0
http response stream 字节流 接收与解码

在接收图片、音频、视频的时候,需要用到二进制流。 浏览器会发给客户端 字节Byte流,一串串的发过来_int8格式 -128~127(十进制),也就是8bit(位)。 客户端接收的时候,对接收到的字节收集,...

大灰狼wow
今天
8
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部