`
javappx
  • 浏览: 9885 次
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

黑马程序员-多线程(1)

 
阅读更多

------- android培训java培训、期待与您交流! ----------

 
 
11.01 概述
 
 

线程 是程序中的执行线程。Java 虚拟机允许应用程序并发地运行多个执行线程。

每个线程都有一个优先级,高优先级线程的执行优先于低优先级线程。每个线程都可以或不可以标记为一个守护程序。当某个线程中运行的代码创建一个新 Thread 对象时,该新线程的初始优先级被设定为创建线程的优先级,并且当且仅当创建线程是守护线程时,新线程才是守护程序。

当 Java 虚拟机启动时,通常都会有单个非守护线程(它通常会调用某个指定类的 main 方法)。Java 虚拟机会继续执行线程,直到下列任一情况出现时为止:

  • 调用了 Runtime 类的 exit 方法,并且安全管理器允许退出操作发生。
  • 非守护线程的所有线程都已停止运行,无论是通过从对 run 方法的调用中返回,还是通过抛出一个传播到 run 方法之外的异常。

创建新执行线程有两种方法。一种方法是将类声明为 Thread 的子类。该子类应重写 Thread 类的 run 方法。接下来可以分配并启动该子类的实例。例如,计算大于某一规定值的质数的线程可以写成:

 


     class PrimeThread extends Thread {
         long minPrime;
         PrimeThread(long minPrime) {
             this.minPrime = minPrime;
         }
 
         public void run() {
             // compute primes larger than minPrime
              . . .
         }
     }
 

然后,下列代码会创建并启动一个线程:

 

     PrimeThread p = new PrimeThread(143);
     p.start();
 

创建线程的另一种方法是声明实现 Runnable 接口的类。该类然后实现 run 方法。然后可以分配该类的实例,在创建 Thread 时作为一个参数来传递并启动。采用这种风格的同一个例子如下所示:

 


     class PrimeRun implements Runnable {
         long minPrime;
         PrimeRun(long minPrime) {
             this.minPrime = minPrime;
         }
 
         public void run() {
             // compute primes larger than minPrime
              . . .
         }
     }
 

然后,下列代码会创建并启动一个线程:

 

     PrimeRun p = new PrimeRun(143);
     new Thread(p).start();
 

每个线程都有一个标识名,多个线程可以同名。如果线程创建时没有指定标识名,就会为其生成一个新名称。

 

 

 
 
/*
进程:是一个正在执行中的程序
每一个进程执行都有一个执行顺序,该顺序是一个执行路径,或者叫一个控制单元
 
线程:就是进程中一个独立的控制单元
线程在控制着进程的执行
 
一个进程中至少有一个线程
 
Java Vm 启动的时候就有一个进程java.exe
该进程中至少有一个线程在负责java程序的执行
而且这个线程运行的代码存在于main方法中
 
该线程称之为主线程
扩展:其实jvm,启动的时候不只一个线程,还有负责垃圾回收机制的线程
1。如何在自定义的代码中,自定义一个线程呢?
通过对api(Application Programming Interface,应用程序编程接口)的查找,java已经提供了对线程这类事物的描述,就是Thread类
 
 
11.02  创建线程-继承Thread类
 
 
创建线程的第一种方式:继承Thread类
步骤;
1,定义类,继承Thread类
2。复写run方法
目的:将自定义的代码存储在run方法中,让线程运行
3,创建一个对象,执行start方法,
该方法有两个作用:启动线程,调用run
 
 
发现运行结果每一次都不同
因为多个线程都获取cpu的执行权,cpu执行到谁,谁就运行
明确一点,在某一个时刻,只能有一个程序执行(多核除外)
cpu在做着快速的切换,以达到看上去是同时运行的效果
我们可以形象把多线程的运行形容为在互相抢夺cpu的执行权
 
这就是多线程的一个特性:随机性,谁抢到谁执行,至于执行多长,cpu说的算
这个过程是随机的
 
11.03 run start的特点
 
 
为什么要覆盖run方法呢?
Thread用于描述线程
该类就定义了一个功能(run function),用于存储线程要运行的代码,该功能就是run方法
 
也就是Thread类中的run方法,用于存储线程要运行的代码(主线程存在于main方法中)
*/
 
class Demo extends Thread
{
	public void run()
	{
		for (int x=0;x<60;x++)
			System.out.println("demo run--"+x);
	}
}

class  ThreadDemo
{
	public static void main(String[] args)
	{
		Demo d = new Demo();//创建好了一个线程
		d.start();//开启线程,并调用该线程的run方法
		//d.run();//仅仅是调用了对象方法,线程没有启动,是主线程的动作

		for (int x = 0;x < 60;x++ )
		{
			System.out.println("Hello World!--"+x);
		}
	}
}
 
 
11.04 线程练习
 
第11天-06-多线程(获取线程对象以及名称)
 
/*
线程都有自己的名称,通过getName函数获取
Thread-编号,该编号从0开始
 
static Thread currentThread();获取当前线程对象
 
设置线程名称:setName或者构造函数(super关键字)
*/
 
class Test extends Thread
{
	// private String name;
	Test(String name)
	{
		//this.name = name;//构造函数和成员变量不能在成员方法中,是独立存在的
		super(name);	
	}
	public void run()
	{	
		for (int x= 0;x < 60; x++)
		{
			System.out.println((Thread.currentThread()==this)+"--test--"+x+"--"+this.getName());
		}
		
	}
}

class  ThreadTest
{
	public static void main(String[] args) 
	{
		Test t1 = new Test("one--");
		Test t2 = new Test("two++");
		t1.start();
		t2.start();

		for (int x = 0;x < 60; x++)
		{
			System.out.println("--main--" + x);
		}
		
	}
}
 
 
11.05 线程运行状态 
 
 
 

 
 
 
11.07 售票的例子
11.08实现RUNABLE接口
 
 
/*
需求:简单的卖票程序
多个窗口同时卖票
 
程序运行后发现了一个问题:
1.卖票的时候有重复行为,这时考虑将tick设置为静态共享数据
但是静态有其局限性;
2.也可以考虑创建一个线程让他执行四次,但是运行会报告线程异常,一个线程被启动了四次,明显是
一种浪费而且不符合程序设计初衷
3。这时就考虑线程创建的问题了
------------------------------
 
 
线程创建的第二种方式:实现Runnable接口
 
步骤:
1.定义类实现Runnable接口
2,覆盖Runnable接口中的run方法
将线程要运行的代码存在于该run方法中
3,通过Thread类建立线程对象
4.将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数
 
5.调用Thread类的strat方法开启线程并调用Runnable接口子类的run方法
------------------------------------
实现方式和继承方式有什么区别吗?
 
继承方式时,只能单继承,想要实现多线程就要创建一个子类对象,子类对象运行的时候会调用run方法,多个对象调用的时候会重复调用run方法中的代码,等于多个人在做一件事情,是一种浪费
 
实现方式时,将Runnable接口的子类创建的对象作为参数传递给Thread的构造函数,这时Thread类创建的对象会运行多个线程,但是执行的代码是同一块代码,等于多个人在一起做一件事情,效率更高也没有浪费
 
-------------------------------------------------------------
实现方式好处:避免了单继承的局限性
在定义线程时,建议使用实现方式
*/
class Ticket implements Runnable
{
	private //static  int tick = 100;
	public void run()
	{
		while (true)
		{
			if (tick > 0)
			System.out.println("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();//这四个对象此时调用start方法调用的run方法,调用的Ticket类的对象只有一个,就是Runnable类接口的子类所创建的Ticket类对象t
	}
}
 
 
 
 
11.09 多线程的安全的问题
11.10同步代码块
 
/*
通过分析,发现打印出0.-1.-2等错票
 
 
多线程的运行出现了安全问题:
 
问题的原因:
当多条线程在操作同一个共享数据时,一条线程对这个数据只执行了一部分,,还没有执行完
另一个线程参与进来执行,导致共享数据的错误(代码中tick的判断出现了错误)
解决方案:
对多条线程执行操作共享数据时,只能让一个线程都执行完,在执行过程中其他不可以参与执行
 
java中内置了解决方式:
同步代码块
 synchronized(对象)
 {
需要被同步的代码
 }
 
同步的前提;
1。必须要有两个或两个以上的线程
2。必须是多个线程使用同一个锁
 
必须保证同步中只有一个线程在运行
 
好处;解决了多线程的安全问题
弊端:多个线程都需要判断锁,较为消耗资源
*/
 
class Ticket implements Runnable
{
	private int tick = 10000;
	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--);
			}
		}
	}
}

class  TicketDemo2
{
	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();
	}
}
 
 
 
11.11 同步函数
 
/*
需求:
银行有一个金库,有两个储户分别存300元,每次存100,存3次
 
目的:该程序是否有安全问题,如果有,如何解决?
 
如何找问题;
1,明确哪些代码是多线程运行代码
2,明确共享数据
3。明确多线程运行代码中哪些语句是操作共享数据的
*/
 
class Bank
{
	private int sum;
	Object obj = new Object();
	public synchronize//或则  void add(int n)
	{
		synchronized(obj)
		{
			sum = sum + n;
			try
			{
				Thread.sleep(10);
			}
			catch (Exception e)
			{
			}//这个函数可以抛出
			System.out.println("sum="+sum);
		}
	}
}

class Cus implements Runnable
{
	private Bank b = new Bank();
	public void run()
	{
		for (int x = 0; x < 3; x++)
		{
			b.add(100);
		}
	}
}


class  BankDemo
{
	public static void main(String[] args) 
	{
		Cus c = new Cus();
		Thread t1 = new Thread(c);
		Thread t2 = new Thread(c);
		t1.start();
		t2.start();
	}
}
 
11.12 同步函数的锁是this
 
/*
同步函数使用的锁是this
 
 
 
*/
 
 
 
class Ticket implements Runnable
{
	private int tick = 100;
	boolean flag = true;
	public void run()
	{
		if (flag)
		{
			while (true)
			{	
				synchronized(this)
				{
					if(tick > 0)
					{
						try{Thread.sleep(10);}catch (Exception e){}
						System.out.println(Thread.currentThread().getName()+"--code--"+tick--);
					}
				}
			}
        }
		else 
			while (true)
				show();
	}
	public synchronized void show()
	{
		if (tick > 0)
		{
			try{Thread.sleep(10);}catch (Exception e){}
			System.out.println(Thread.currentThread().getName()+"--show--"+tick--);
		}
	}
}

class  ThislockDemo
{
	public static void main(String[] args) 
	{
		Ticket t = new Ticket();
		Thread t1=new Thread(t);
		Thread t2=new Thread(t);
		t1.start();
		try{Thread.sleep(10);}catch (Exception e){}
		t.flag = false;
		t2.start();
	}
}
 
 
11.13 静态同步函数的锁是Class对象
 
 
/*
如果同步函数被静态修饰后,使用的锁是什么呢?
通过验证发现不再是this了
 
静态方法中也不会有this
 
静态进内存时,内存中没有本类对象,但是一定有该类对应的字节码文件对象
类名.class,该对象的类型是Class
 
静态的同步方法使用的锁是该方法所在类的字节码文件对象,类名.class
 
*/
 
 
 
class Ticket implements Runnable
{
	private static int tick = 100;
	//Object obj = new Object();
	boolean flag = true;
	public void run()
	{
		if (flag)
		{
			while (true)
			{	
				synchronized(Ticket.class)
				{
					if(tick > 0)
					{
						try{Thread.sleep(10);}catch (Exception e){}
						System.out.println(Thread.currentThread().getName()+"--code--"+tick--);
					}
				}
			}
        }
		else 
			while (true)
				show();
	}
	public static synchronized void show()
	{
		if (tick > 0)
		{
			try{Thread.sleep(10);}catch (Exception e){}
			System.out.println(Thread.currentThread().getName()+"--show--"+tick--);
		}
	}
}

class  StaticMethodDemo
{
	public static void main(String[] args) 
	{
		Ticket t = new Ticket();
		Thread t1=new Thread(t);
		Thread t2=new Thread(t);
		t1.start();
		try{Thread.sleep(10);}catch (Exception e){}
		t.flag = false;
		t2.start();
	}
}
 
 
 
 
11.14 单例设计模式 懒汉式
 
 
 
class Single//懒汉式
{
	private static Single s = null; 
	private Single(){}

	public static //synchronized Single getInstance()//可以用同步函数或者同步代码块解决多线程访问的安全问题,但是相比较同步代码块效率更高
	{
		if (s==null)//多线程访问时会存在安全问题,需要同步
		{
			synchronized(Single.class)// 什么意思?
			{	if(s==null)
				s = new Single();
				
			}
		}
                retrun s;
	}
}

//饿汉式
class Single
{
	private static final Single s = new Single();
	private Single(){}

	public static  getInstance()
	{
		return s;
	}
}
 
 
 
 
11.15多线程-死锁
 
 
/*
死锁;
同步中嵌套同步
 
 
*/class Ticket implements Runnable
{
	private int tick = 100;
	boolean flag = true;
	Object obj = new Object();
	public void run()
	{
		if (flag)
		{
			while (true)
			{	
				synchronized(obj)
				{
					show();
				}
			}
        }
		else 
			while (true)
				show();
	}
	public synchronized void show()
	{
		synchronized(obj)
				{
					if(tick > 0)
					{
						try{Thread.sleep(10);}catch (Exception e){}
						System.out.println(Thread.currentThread().getName()+"--code--"+tick--);
					}
				}
	}
}

class  DeadLockDemo
{
	public static void main(String[] args) 
	{
		Ticket t = new Ticket();
		Thread t1=new Thread(t);
		Thread t2=new Thread(t);
		t1.start();
		try{Thread.sleep(10);}catch (Exception e){}
		t.flag = false;
		t2.start();
	}
}
 
 
 
 
 
 
 
简单版本:
class Test implements Runnable
{
	private boolean flag;
	Test(boolean flag)
	{
		this.flag=flag;
	}
	public void run();
	{
		if(flag)
		{        while(true)
                        {
			synchronized(locka)
			{
				System.out.println("if lcoka ");
				synchronized(lockb)
				{
					System.out.println("if lockb");
				}
			}
                        }
		}
		else()
		{
			synchronized(lockb)
			{
				System.out.println("else lockb");
				synchronized(locka)
				{
					System.out.println("else locka");
				}
			}
		}
	}
}

class MyLock
{
		Object locka=new Object();
		Object lockb=new Object();

}




class  
{
	public static void main(String[] args) 
	{
		Thread t1 = new Thread(new Test(true));
		Thread t2 = new Thread(new Test(false));
		t1.start();
		t2.start();
	}
}
 
  • 大小: 193.9 KB
分享到:
评论

相关推荐

    黑马程序员-java多线程技术01

    NULL 博文链接:https://huangminwen.iteye.com/blog/1157983

    多线程高新(黑马程序员)

    NULL 博文链接:https://lvwenwen.iteye.com/blog/1470696

    黑马程序员–Java多线程讲解笔记

    当一个进程中线程有多个时,是多线程。  为什么要用多线程  1,让计算机"同时"做多件事情,节约时间。  2,后台运行程序,提高程序的运行效率.。  3,多线程可以让程序"同时"处理多个事情。  4,...

    黑马程序员_张孝祥_Java多线程与并发库 视频+代码+资料

    黑马程序员_张孝祥_Java多线程与并发库,视频+代码+资料

    传智播客.黑马程序员《Java 基础入门》课后习题答案

    1、 面向对象、跨平台性、健壮性、安全性、可移植性、多线程性、动态性等。 2、 JRE(Java Runtime Environment,Java 运行时环境),它相当于操作系统部分,提供了 Java 程序运 行时所需要的基本条件和许多 Java ...

    黑马程序员_张孝祥_Java多线程与并发库

    黑马程序员_张孝祥_Java多线程与并发库,老师讲的非常仔细,老师很有耐心.欢迎大家下载学习.

    传智播客_Java培训_毕向东_Java基础[05-多线程]

    传智播客_Java培训_毕向东_Java基础[05-多线程]系黑马程序员_毕向东_Java基础视频教程

    黑马程序员 安卓学院 万元哥项目经理 分享220个代码实例

    |--利用FinalHttp实现多线程断点续传 |--加密之MD5 |--动画Animation详解 |--动画之view左右抖动 |--动画之移动动画 |--动画之组合动画 |--动画之缩放动画ScaleAnimation |--反序列化对象 |--发送短信 读天气 调音量...

    图解java多线程设计模式

    日本资-深技术作家、《程序员的数学》作者结城浩执笔,264张图表(UML类图、时序图、Timethreads图等)穿插文中,通过类比手法和浅显的语言,逐一讲解与多线程和并发处理相关的12种设计模式。每章附带练习题和答案,...

    java拼图游戏源码.zip

    这是一个java写的拼图游戏,用了swing、多线程等知识,可以设置行数列、列数、还有使用多线程写的游戏动画,拼图的图块具有磁贴设计,代码封装性较强,容易移植,纯原创。

    图解java多线程设计模式2017年8月最新版

    精选12种与多线程和并发处理相关的设计模式 264张图表 + 300段Java示例程序 = 轻松学习多线程编程 日本经典多线程入门书,原版长销11年! 本书适合以下读者阅读 a.对多线程感兴趣的人 b.对Java编程感兴趣的人 c.对...

    拼图游戏 (源码+所有文件)

    萌新做的一个简单的Java拼图游戏 启动类:pers.sept.jigsaw1.swing下的...多线程。 下拉列表选择数字可以切换关卡图片,最后的“+”,可以添自己的图片到关卡中。 设有背景音乐 有一键通过按钮 等等,块下载去看看吧。

    java并发库高级应用源码--张孝祥

    java并发库thread使用,传统线程技术、定时器技术、线程互斥技术,同步通讯技术、多线程共享数据、并发库应用,线程锁技术,阻塞锁、阻塞队列,线程池等应用

    《Java基础案例教程(第2版)》课后习题答案1

    第1章 Java开发入门一.填空题1. 面向对象,SUN 2. JavaSE,JavaEE,JavaME3.面向对象、跨平台性、支持多线程4. JDK5.bin

    图解java多线程设计模式 2017年8月最新版

    这本书的pdf文件有162M,是最新版高清的pdf,网上原书售价60多元,这里提供的附件是百度云的链接地址。

    java7源码-Java-concurrent:Java并发编程

    黑马程序员——Java异步课程源码 plugin Lombok logback.xml 说明 课堂代码主要在 case_java8 子模块内,按章节划分, io.github.hank.java.concurrent.n2 - 同步与异步 io.github.hank.java.concurrent.n3 - Java...

    学成在线-分布式任务视频处理

    2.适用于黑马程序员Java企业级实战开发《学成在线》微服务项目,基于SpringCloud、SpringCloudAlibaba技术栈开发。 3.采用xxl-job技术。 4.步骤概要: 4.1 作业分片方案 4.2 保证任务不重复执行 4.3 业务流程 5....

    黑马JVM学习笔记二

    title: 黑马JVM学习笔记二 date: 2020-01-13 1:00:00 ...线程是私有的,多线程之间分别有各自的程序计数器记录对应线程的执行位置 程序计数器是Java虚拟机规范中唯一一个不会存在内存溢出的区(堆和栈等会出现内存溢

    JAVA核心知识点整理.pdf

    给大家分享一篇我在学习java过程中...包含常见的面试题:JVM、Java集合、多线程并发、java基础、SSM框架原理、微服务、Netty和RPC、网络、日志、算法、数据结构、加密、分布式算法、机器学习、大数据等知识点,都是干货

    mfc教程(word版)

    第1章 MFC概述 1 1.1 MFC是一个编程框架 1 1.1.1 封装 1 1.1.2 继承 2 1.1.3 虚拟函数和动态约束 2 1.1.4 MFC的宏观框架体系 2 1.2 MDI应用程序的构成 3 1.2.1 构成应用程序的对象 3 1.2.2 构成应用程序的对象之间的...

Global site tag (gtag.js) - Google Analytics