文档章节

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面试需要准备哪些多线程并发的技术要点

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

码蚁说架构
05/31
0
0
JAVA基础再回首(二十四)——多线程的概述、实现方式、线程控制、生命周期、多线程程序练习、安全问题的解决

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/m366917/article/details/52711906 JAVA基础再回首(二十四)——多线程的概述、实现方式、线程控制、生命周期...

Aduroidpc
2016/09/30
0
0
Java面试:投行的15个多线程和并发面试题

本文由ImportNew -一杯哈希不加盐 翻译自dzone。欢迎加入翻译小组。转载请见文末要求。 多线程和并发问题已成为各种 Java 面试中必不可少的一部分。如果你准备参加投行的 Java 开发岗位面试,...

ImportNew
08/23
0
0
【转】15个顶级Java多线程面试题及回答

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

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

没有更多内容

加载失败,请刷新页面

加载更多

nginx的简单使用:负载均衡

nginx:反向代理的服务器;用户发送请求到nginx,nginx把请求发送给真正的服务器,等待服务器处理完数据并返回,再把数据发送给用户。 nginx作为一个反向代理服务器,能缓存我们项目的静态文...

osliang
12分钟前
1
0
网站title标题被改并被百度网址安全中心提醒的解决办法

国庆假日期间我们Sine安全接到众多网站站长求助网站标题被改导致在百度搜索中百度安全中心提醒被拦截,导致网站正常用户无法浏览网站被跳转到一些菠菜du博网站,而且很明显的一个特征就是在百...

网站安全
14分钟前
1
0
JDK版本与major.minor version的对照关系

其实,只需要记住jdk6对于major.minor version 50即可,其他版本自行计算即可。 ---------------------

码代码的小司机
16分钟前
1
0
Gitlab安装

具体步骤如下: sudo yum install -y curl policycoreutils-python openssh-server cronie sudo lokkit -s http -s ssh sudo yum install postfix sudo service postfix start sudo chkconfi......

很好亦平凡ms
23分钟前
1
0
C++基础教程面向对象学习笔记及心得感悟[图]

C++基础教程面向对象学习笔记及心得感悟[图] 使用友元函数重载算术运算符: C ++中一些最常用的运算符是算术运算符 - 即加号运算符(+),减运算符( - ),乘法运算符(*)和除法运算符(/...

原创小博客
24分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部