java学习之多线程
进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。
线程(Lightweight
 Process,LWP)是程序中一个单一的顺序控制流程,有时被称为轻量级进程,是程序执行流的最小单元。进程内一个相对独立的、可调度的执行单元,是系统独立调度和分派CPU的基本单位指运行中的程序的调度单位。在单个程序中同时运行多个线程完成不同的工作,称为多线程。
每一个单进程==多个线程的组合
javav中线程实现的两种方式:
1.继承Thread类
首先覆盖Thread中的run方法
public class MyThread extends Thread {
	private String name; // 定义name属性
	public MyThread(String name) {
		this.name = name;
	}
	public void run() {// 覆写run()方法
		for (int i = 0; i < 50; i++) {// 表示循环10次
			System.out.println("Thread运行:" + name + ",i = " + i);
		}
	}
}
因为线程的启动需要借助底层函数,因此无法通过实例化MyThread后调用run方法直接完成,而必须通过可以启动底层函数的start()方法来启动线程。
public class ThreadDemo02 {
	public static void main(String[] args) {
		MyThread mt1 = new MyThread("线程A");
		MyThread mt2 = new MyThread("线程B");
		mt1.start(); // 调用线程体
		mt2.start(); // 调用线程体
	}
}
start()方法在jdk1.5中的源码
2.实现Runnable接口
public class MyThread implements Runnable { // 实现Runnable接口
	private String name; // 定义name属性
	public MyThread(String name) {
		this.name = name;
	}
	public void run() {// 覆写run()方法
		for (int i = 0; i < 50; i++) {// 表示循环10次
			System.out.println("Thread运行:" + name + ",i = " + i);
		}
	}
}
public class RunnableDemo01 {
	public static void main(String[] args) {
		MyThread mt1 = new MyThread("线程A");
		MyThread mt2 = new MyThread("线程B");
		new Thread(mt1).start(); // 调用线程体
		new Thread(mt2).start(); // 调用线程体
	}
}
通常开发中多用到第二种方法,因为相比于法一,既可以避免单继承局限,又可以实现现资源共享。
法一实现代码:
public class MyThread extends Thread {// 继承Thread类
	private int ticket = 5; // 一共才5张票
	public void run() {// 覆写run()方法
		for (int i = 0; i < 50; i++) {// 表示循环10次
			if (this.ticket > 0) {
				System.out.println("卖票:ticket = " + this.ticket--);
			}
		}
	}
}
public class ThreadTicket {
	public static void main(String[] args) {
		MyThread mt1 = new MyThread(); // 一个线程
		MyThread mt2 = new MyThread(); // 一个线程
		MyThread mt3 = new MyThread(); // 一个线程
		mt1.start() ;	// 开始卖票
		mt2.start() ;	// 开始卖票
		mt3.start() ;	// 开始卖票
	}
}
法二实现代码
public class MyThread implements Runnable {// 实现Runnable接口
	private int ticket = 5; // 一共才5张票
	public void run() {// 覆写run()方法
		for (int i = 0; i < 50; i++) {// 表示循环10次
			if (this.ticket > 0) {
				System.out.println("卖票:ticket = " + this.ticket--);
			}
		}
	}
}
public class RunnableTicket {
	public static void main(String[] args) {
		MyThread mt = new MyThread(); // 一个线程
		new Thread(mt).start() ;	// 开始卖票
		new Thread(mt).start() ;	// 开始卖票
		new Thread(mt).start() ;	// 开始卖票
	}
}
很明显法二只有一个线程,共同售卖5张票而法一三个独立的线程各卖出了5张票。
线程的操作:
设置和取得名字
public class MyThread implements Runnable {
	public void run() {
		for (int i = 0; i < 10; i++) {
			System.out.println(Thread.currentThread().getName() + "线程正在运行。");
		}
	}
}
设置线程名字分别为A、B、C
public class ThreadNameDemo01 {
	public static void main(String[] args) {
		MyThread mt = new MyThread(); // Runnable子类实例
		Thread thread1 = new Thread(mt, "线程A");
		Thread thread2 = new Thread(mt, "线程B");
		Thread thread3 = new Thread(mt, "线程C");
		thread1.start() ;
		thread2.start() ;
		thread3.start() ;
	}
}
在java中,至少会同时执行两个进程,分别为Main线程和GC(java垃圾回收)
public class ThreadNameDemo02 {
	public static void main(String[] args) {
		MyThread mt = new MyThread(); // Runnable子类实例
		new Thread(mt, "自定义线程").start();
		mt.run() ;	// 直接通过对象调用
	}
}
线程的休眠
	public void run() {
		for (int i = 0; i < 10; i++) {
			try {
				Thread.sleep(500); // 每个休眠500毫秒
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName() + "线程正在运行。");
		}
	}
}
public class ThreadSleepDemo {
	public static void main(String args[]){
		MyThread mt = new MyThread() ;
		new Thread(mt,"线程A").start() ;
		new Thread(mt,"线程B").start() ;
	}
}
线程的中断
class MyThread implements Runnable {
	public void run() {
		System.out.println("1、进入run()方法体");
		try {
			System.out.println("2、线程休眠20秒钟");
			Thread.sleep(20000); // 每个休眠20秒
			System.out.println("3、线程正常休眠20秒钟");
		} catch (InterruptedException e) {
			System.out.println("4、线程休眠被中断");
			return;// 返回方法调用处
		}
		System.out.println("5、正常结束run()方法体");
	}
}
public class InterruptDemo {
	public static void main(String[] args) {
		MyThread mt = new MyThread();
		Thread thread = new Thread(mt, "线程A");
		thread.start();// 启动线程
		try {
			Thread.sleep(2000); // 保证程序至少执行2秒
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		thread.interrupt(); // 中断
	}
}
设置线程优先级
class MyThread implements Runnable {
	public void run() {
		for (int i = 0; i < 10; i++) {
			try {
				Thread.sleep(600) ;	// 延迟操作
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName() + "线程正在运行。");
		}
	}
}
public class PriorityDemo01 {
	public static void main(String[] args) {
		MyThread mt = new MyThread();
		Thread t1 = new Thread(mt, "线程A");
		Thread t2 = new Thread(mt, "线程B");
		Thread t3 = new Thread(mt, "线程C");
		t1.setPriority(Thread.NORM_PRIORITY); // 将第一个线程设置为中等优先级
		t3.setPriority(Thread.MAX_PRIORITY); // 将第三个线程设置为最高优先级
		t2.setPriority(Thread.MIN_PRIORITY); // 将第二个线程设置为最低优先级
		t1.start();
		t2.start();
		t3.start();
	}
}
主方法优先级属于普通优先级。
线程的同步
首先看一个异常售票实例
class MyTicketThread implements Runnable {// 实现Runnable接口
	private int ticket = 5; // 一共才5张票
	public void run() {// 覆写run()方法
		for (int i = 0; i < 50; i++) {// 表示循环10次
			if (this.ticket > 0) {
				try {
					Thread.sleep(300);// 延迟
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println("卖票:ticket = " + this.ticket--);
			}
		}
	}
}
public class SynDemo01 {
	public static void main(String[] args) {
		MyTicketThread mt = new MyTicketThread(); // 一个线程
		new Thread(mt, "票贩子-A ").start(); // 开始卖票
		new Thread(mt, "票贩子-B ").start(); // 开始卖票
		new Thread(mt, "票贩子-C ").start(); // 开始卖票
	}
}
因为延迟,可能导致售票发生数值异常。
解决办法一:利用synchronized方法设置同步代码使售票程序同步起来,同一时间段只允许一个线程访问、
class MyTicketThread implements Runnable {// 实现Runnable接口
	private int ticket = 5; // 一共才5张票
	public void run() {// 覆写run()方法
		for (int i = 0; i < 50; i++) {// 表示循环10次
			synchronized (this) {// 形成同步代码块
				if (this.ticket > 0) {
					try {
						Thread.sleep(300);// 延迟
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					System.out.println("卖票:ticket = " + this.ticket--);
				}
			}
		}
	}
}
public class SynDemo02 {
	public static void main(String[] args) {
		MyTicketThread mt = new MyTicketThread(); // 一个线程
		new Thread(mt, "票贩子-A ").start(); // 开始卖票
		new Thread(mt, "票贩子-B ").start(); // 开始卖票
		new Thread(mt, "票贩子-C ").start(); // 开始卖票
	}
}
解决方法二:设定同步方法
class MyTicketThread implements Runnable {// 实现Runnable接口
	private int ticket = 5; // 一共才5张票
	public void run() {// 覆写run()方法
		for (int i = 0; i < 50; i++) {// 表示循环10次
			this.sale(); // 调用同步方法
		}
	}
	public synchronized void sale() {// 增加同步方法
		if (this.ticket > 0) {
			try {
				Thread.sleep(300);// 延迟
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println("卖票:ticket = " + this.ticket--);
		}
	}
}
public class SynDemo03 {
	public static void main(String[] args) {
		MyTicketThread mt = new MyTicketThread(); // 一个线程
		new Thread(mt, "票贩子-A ").start(); // 开始卖票
		new Thread(mt, "票贩子-B ").start(); // 开始卖票
		new Thread(mt, "票贩子-C ").start(); // 开始卖票
	}
}
线程的死锁
所谓死锁: 是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。
class FanBo {
	public synchronized void say(ZhangYang zy) {
		System.out.println("把钱给我,放了你弟弟。");
		zy.give();
	}
	public synchronized void give() {
		System.out.println("得到了钱,同时被警察抓了。");
	}
}
class ZhangYang {
	public synchronized void say(FanBo fb) {
		System.out.println("把弟弟放了,我给你钱。");
		fb.give();
	}
	public synchronized void give() {
		System.out.println("弟弟救回来,同时报案了。");
	}
}
public class DeadLockDemo implements Runnable {
	private FanBo fb = new FanBo();
	private ZhangYang zy = new ZhangYang();
	public DeadLockDemo() {
		new Thread(this).start() ;
		zy.say(fb);
	}
	public void run() {
		fb.say(zy);
	}
	public static void main(String[] args) {
		new DeadLockDemo();
	}
}
多个进程共享统一资源的时候需要同步,而过多的同步又会产生死锁。
java学习之多线程的更多相关文章
- 0037 Java学习笔记-多线程-同步代码块、同步方法、同步锁
		什么是同步 在上一篇0036 Java学习笔记-多线程-创建线程的三种方式示例代码中,实现Runnable创建多条线程,输出中的结果中会有错误,比如一张票卖了两次,有的票没卖的情况,因为线程对象被多条 ... 
- Java学习笔记-多线程-创建线程的方式
		创建线程 创建线程的方式: 继承java.lang.Thread 实现java.lang.Runnable接口 所有的线程对象都是Thead及其子类的实例 每个线程完成一定的任务,其实就是一段顺序执行 ... 
- 2019/3/7    Java学习之多线程(基础)
		Java学习之多线程 讲到线程,就必须要懂得进程,进程是相当于一个程序的开始到结束,而线程是依赖于进程的,没有进程,就没有线程.线程也分主线程和子线程,当在主线程开启子线程时,主线程结束,而子线程还可 ... 
- java学习笔记 --- 多线程(多线程的创建方式)
		1.创建多线程方式1——继承Thread类. 步骤: A:自定义类MyThread继承Thread类. B:MyThread类里面重写run()? 为什么是run()方法呢? C:创建对象 D:启 ... 
- Java学习之多线程详解
		一.多线程的实现 1.继承Thread类  a.子类继承Thread类具备多线程能力  b.启动线程:子类对象.start()  c.不建议使用:避免OOP单继承局限性 package com. ... 
- JAVA学习总结-多线程基础:
		参考书籍:疯狂JAVA讲义 1.进程和线程; 进程是处于运行过程中的程序;并且具有一定的独立功能;进程是系统进行系统资源分配和调度的一个独立单位. 一般而言,进程包括以下三个特征: 独立性:进程是系统 ... 
- JAVA学习笔记 -- 多线程之共享资源
		在多线程程序执行过程中,可能会涉及到两个或者多个线程试图同一时候訪问同一个资源.为了防止这样的情况的发生,必须在线程使用共享资源时给资源"上锁",以阻挡其他线程的訪问. 而这样的机 ... 
- 0041 Java学习笔记-多线程-线程池、ForkJoinPool、ThreadLocal
		什么是线程池 创建线程,因为涉及到跟操作系统交互,比较耗费资源.如果要创建大量的线程,而每个线程的生存期又很短,这时候就应该使用线程池了,就像数据库的连接池一样,预先开启一定数量的线程,有任务了就将任 ... 
- 0040 Java学习笔记-多线程-线程run()方法中的异常
		run()与异常 不管是Threade还是Runnable的run()方法都没有定义抛出异常,也就是说一条线程内部发生的checked异常,必须也只能在内部用try-catch处理掉,不能往外抛,因为 ... 
随机推荐
- scikit-learn的主要模块和基本使用
			1.加载数据(Data Loading) 假设输入是特征矩阵或者csv文件,首先数据被载入内存. scikit-learn的实现使用了NumPy中的arrays,所以,使用NumPy来载入csv文件. ... 
- python语言
			python语言 因为我比较熟悉python语言,所以月刊中python语言的项目居多,个人能力有限,其他语言涉及甚少,欢迎各路人士加入,丰富月刊的内容. 当然,如果您有更好的建议或者意见,欢迎发邮件 ... 
- WPF中PasswordBox控件无法绑定Password属性解决办法
			在WPF中,默认的Password控件的Password属性是不允许为之绑定的,下面是一个解决绑定Password的方法的代码: 1.前台代码 <Window x:Class="Pas ... 
- 安装 Archlinux 小记
			故事的背景 开始的时候装的 win8 + ubuntu 双系统,但是慢慢感觉只要有 windows 存在,在 Linux 上遇到问题了就想逃回去. 在一次 GDG 的演讲中听到的: 趁现在还年轻,还有 ... 
- BuildSigar
			https://support.hyperic.com/display/SIGAR/Home;jsessionid=7436F86CA13B66BCE1A827043E159F34#Home-down ... 
- 如何在同一系统里同时启动多个Tomcat
			需要在同一系统里启动多个tomcat,应该怎么处理? tomcat是个服务程序,需要占用几个通讯端口,所以默认情况是不能启动多个tomcat,如果要启动多个tomcat,需要修改配置文件,通过在配置文 ... 
- Twitter 新一代流处理利器——Heron 论文笔记之Heron架构
			Twitter 新一代流处理利器--Heron 论文笔记之Heron架构 标签(空格分隔): Streaming-process realtime-process Heron Architecture ... 
- [ACM] hdu 2191 珍惜如今,感恩生活 (多重背包)
			Problem Description 急!灾区的食物依旧短缺! 为了拯救灾区同胞的生命,心系灾区同胞的你准备自己採购一些粮食支援灾区,如今如果你一共同拥有资金n元,而市场有m种大米,每种大米都是袋装 ... 
- 列"xx"不在表Table中
			在数据库中用了left join来查一个表的所有列和另一个表的一个列,但无论用IDataReader还是DataSet都不能获取到另一个表的列,调试时总是说没有那个值,但在数据库中执行语句又有.一直想 ... 
- [STL源码剖析]RB-tree的插入操作
			RB-tree的性质 对于RB-tree,首先做一个了解,先看一张维基百科的RB-tree: 再看RB-tree的性质: 性质1. 节点是红色或黑色. 性质2. 根是黑色,所有叶子都是黑色(叶子节点指 ... 
