1.理清概念 并行与并发:
*并行:多个cpu实例或者多台机器同时执行一段处理逻辑,是真正的同时。
*并发:通过cpu调度算法,让用户看上去同时执行,实际上从cpu操作层面不是真正的同时。并发往往在场景中有公用的资源,那么针对这个公用的资源往往产生瓶颈,我们会用TPS或者QPS来反应这个系统的处理能力。 2.线程创建
* 继承thread类创建多线程 public class Example01 { public static void main(String[] args) { MyThread myThread = new MyThread(); //创建线程 MyThread 的线程对象
myThread.start(); //开启线程 while(true){
System.out.println("main 方法在运行");
}
}
} class MyThread extends Thread{ public void run(){
while (true){
System.out.println("MyThread 类的 run()方法在运行");
}
}
} * 实现Runnable接口创建线程 public class Example01 {
public static void main(String[] args) { MyThread myThread = new MyThread(); //创建线程 MyThread 的线程对象
Thread thread = new Thread(myThread); //创建线程对象
thread.start(); //开启线程,执行线程中的run()方法 while(true){
System.out.println("main 方法在运行");
}
}
} class MyThread implements Runnable{ public void run(){
while (true){
System.out.println("MyThread 类的 run()方法在运行");
}
}
} * 两种实现多线程方式的对比分析,实现Runnable接口相对于继承Thread类有如下显著的好处
1.可以避免由于java的单继承带来的局限。java不支持多继承(子类不能有多个父类),其他类的子类不能用继承Thread类的方式,只能采用实现Runnable接口的方式
2.适合多个相同程序代码的线程去处理同一个资源的情况,把线程同程序代码、数据有效的分离 * 后台进程
--如果某个线程对象在启动之前调用了setDaemon(true)语句,这个线程就变成一个后台进程
--当前台线程结束后,JVM会通知后台线程
--进程中只有后台线程运行时,进程会结束 3.线程的调度 * 线程的优先级
--static int MAX_PRIORITY 表示线程的最高优先级 相当于值10
--static int MIN_PRIORITY 表示线程的最低优先级 相当于值1
--static int NORM_PRIORITY 表示线程的普通优先级 相当于值5 * 线程休眠
--Thread.sleep() * 线程让步
--Thread.yield() * 线程插队
--join() 4.多线程同步 * 线程安全
--多个线程同时去访问同一个资源时,易引发安全问题。 *同步代码块
class Ticket1 implements Runnable{ private int tickets = 10; //定义变量 赋值
Object lock = new Object(); //定义任意一个对象,用作同步代码块的锁 public void run(){ while (true){
synchronized(lock){ //定义同步代码块 try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
} if(tickets >0){
System.out.println(Thread.currentThread().getName()+"---卖出的票---"+tickets--);
}else{
break;
}
}
} }
} public class Example01 { public static void main(String[] args) {
Ticket1 ticket = new Ticket1(); //创建 Ticket1 对象
//创建并开启四个线程
new Thread(ticket,"线程1").start();
new Thread(ticket,"线程2").start();
new Thread(ticket,"线程3").start();
new Thread(ticket,"线程4").start();
}
} *同步方法
class Ticket1 implements Runnable{ private int tickets = 10; //定义变量 赋值
public void run(){
while (true){
saleTicket();
if(tickets <=0){
break;
}
}
} //定义一个同步方法saleTicket()
private synchronized void saleTicket(){
if(tickets > 0){
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"---卖出的票---"+tickets--);
}
}
} public class Example01 { public static void main(String[] args) {
Ticket1 ticket = new Ticket1(); //创建 Ticket1 对象
//创建并开启四个线程
new Thread(ticket,"线程1").start();
new Thread(ticket,"线程2").start();
new Thread(ticket,"线程3").start();
new Thread(ticket,"线程4").start();
}
} *锁死问题 5.多线程通信 *问题引入:假设有两个线程同时去操作同一个存储空间,其中一个线程负责向存储空间中存入数据,另一个线程负责取出数据。 --数据存储类
public class Storage { //数据存储数组
private int[] cells = new int[10]; //inPos 表示存入时数组下标,outPos表示取出时数组下标
private int inPos,outPos; //定义一个put()方法向数组中存入数据 public void put(int num){
cells[inPos] = num;
System.out.println("在cells["+inPos+"]中放入数据--"+cells[inPos]);
inPos++;
if(inPos == cells.length)
inPos = 0; //当inPos为数组长度时 将其置为0
} //定义一个get()方法从数组中取出数据
public void get(){
int data = cells[outPos];
System.out.println("在cells["+outPos+"]中取出数据--"+data);
outPos++;
if(outPos == cells.length)
outPos = 0; //当outPos为数组长度时 将其置为0
}
} --数据存取类
public class Input implements Runnable { private Storage st;
private int num; Input (Storage st){ //通过构造方法接收一个Storage对象
this.st= st;
} @Override
public void run() {
while(true){
st.put(num++); //将num存入数组,每次存入后num自增
}
}
} public class Output implements Runnable { private Storage st; Output(Storage st){ //通过构造方法接收一个Storage对象
this.st = st;
} @Override
public void run() {
while(true){
st.get();
}
} } --创建线程
public class ExampleTest02 { public static void main(String[] args) { Storage st = new Storage(); //创建数据存储对象
Input input = new Input(st); //创建Input对象传入Storage对象
Output output=new Output(st); //创建Output对象传入Storage对象 new Thread(input).start(); //开启新线程
new Thread(output).start(); //开启新线程
} } * 问题解决:测试发现上述存取进程是随机的,未按照顺序轮流执行。如需按照一定顺序轮流执行,此时需要让进程间进行通信
--在Object类中提供了wait(),notify(),notifyAll()方法用于解决线程间的通信问题,因为Java中的所有类都是Object类的子类或间接子类,因此任何类的实例对象都可以直接使用这些方法。
--void wait() 使当前线程放弃同步锁并进入等待,直到其他线程进入此同步锁,并调用notify()或notifyAll()方法唤醒该线程为止
--void notify() 唤醒此同步锁上等待的第一个调用wait()方法的线程
--void notifyAll() 唤醒此同步锁上调用wait()方法的所有线程
public class Storage {
private int[] cells = new int[10]; //数据存储数组
private int inPos,outPos; //inPos 表示存入时数组下标,outPos表示取出时数组下标
private int count; //存入或取出数据的数量 //定义一个put()方法向数组中存入数据
public synchronized void put(int num){ //存入数据如果等于cells的长度,此线程等待
while(count == cells.length){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
cells[inPos] = num;
System.out.println("在cells["+inPos+"]中放入数据--"+cells[inPos]);
inPos++;
if(inPos == cells.length)
inPos = 0; //当inPos为数组长度时 将其置为0 count++;
this.notify();
} //定义一个get()方法从数组中取出数据
public synchronized void get(){ while(count == 0){ //如果count为0 此线程等待
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
int data = cells[outPos];
System.out.println("在cells["+outPos+"]中取出数据:"+data);
cells[outPos] = 0;
outPos++;
if(outPos == cells.length)
outPos = 0; //当outPos为数组长度时 将其置为0
count--;
this.notify();
}
} 注意:如果wait(),notify(),notifyAll()方法调用者不是同步锁对象,JVM会抛出 java.lang.IllegalMonitorStateException

java(5) 线程的更多相关文章

  1. java之线程

    java之线程 一:线程: 线程是什么呢?线程,有时被称为轻量级进程是程序执行流的最小单元.一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成.另外,线程是进程中的一个实体,是被系统 ...

  2. Java 使用线程方式Thread和Runnable,以及Thread与Runnable的区别

    一. java中实现线程的方式有Thread和Runnable Thread: public class Thread1 extends Thread{ @Override public void r ...

  3. Java的线程安全

    线程安全 我们这里讨论的线程安全,就限定于多个线程之间存在共享数据访问这个前提,因为如果一段代码根本不会与其他线程共享数据,那么从线程安全的角度来看,程序是串行执行还是多线程执行对它来说是完全没有区别 ...

  4. 深入理解Java之线程池

    原作者:海子 出处:http://www.cnblogs.com/dolphin0520/ 本文归作者海子和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则 ...

  5. java中线程分两种,守护线程和用户线程。

    java中线程分为两种类型:用户线程和守护线程. 通过Thread.setDaemon(false)设置为用户线程: 通过Thread.setDaemon(true)设置为守护线程. 如果不设置次属性 ...

  6. java 多线程—— 线程让步

    java 多线程 目录: Java 多线程——基础知识 Java 多线程 —— synchronized关键字 java 多线程——一个定时调度的例子 java 多线程——quartz 定时调度的例子 ...

  7. java 多线程—— 线程等待与唤醒

    java 多线程 目录: Java 多线程——基础知识 Java 多线程 —— synchronized关键字 java 多线程——一个定时调度的例子 java 多线程——quartz 定时调度的例子 ...

  8. Java的线程模型

    并发不一定要依赖多线程(如PHP中很常见的多进程并发),但是在Java里面谈论并发,大多数都与线程脱不开关系. 线程是比进程更轻量级的调度执行单位,线程的引入,可以把一个进程的资源分配和执行调度分开, ...

  9. Java多线程 - 线程状态

    转自: http://www.cnblogs.com/lwbqqyumidi/p/3804883.html 一.线程的生命周期及五种基本状态 关于Java中线程的生命周期,首先看一下下面这张较为经典的 ...

  10. Java Thread线程控制

    一.线程和进程 进程是处于运行中的程序,具有一定的独立能力,进程是系统进行资源分配和调度的一个独立单位. 进程特征: A.独立性:进程是系统中独立存在的实体,可以拥有自己独立的资源,每个进程都拥有自己 ...

随机推荐

  1. dendrogram 和 barplot 的组合

    示例代码: data <- mtcars[1:10, ] hc <- hclust(dist(data)) hcd <- as.dendrogram(hc) par(mfrow = ...

  2. FusionCancer-人类癌症相关的融合基因的数据库

    RNA-seq 测序可以用于融合基因的发现,在过去的十几年里,RNA-seq 测序数据不断增加,发现的融合基因的数据也不断增加: FusionCancer 是一个人类癌症相关的融合基因的数据库,利用N ...

  3. R语言ggplot2-labs 函数

    labs 函数主要有以下三个用途: 1) 设置图片的标题(title), 子标题(subtitle), 引用(caption) 代码示例: ggplot(mtcars, aes(mpg, wt, co ...

  4. browser process request

    What really happens when you navigate to a URL Beginner’s Guide: How IIS Process ASP.NET Request Wha ...

  5. Java初学者不可不知的MyEclipse的设置技巧(自动联想功能)

    最近初学Java,正在使用MyEclipse来编写新的项目,刚开始打开MyEclipse感觉这个工具既陌生又熟悉,熟悉之处在于编辑器的几大共通之处它都具备,比如说基本的设置.编辑区.调试区都是类似的, ...

  6. 设置回车的默认按钮detectEnter

    场景: 页面有一个搜索文本框和搜索按钮.正常情况下,当我在搜索文本框输入关键字后按回车键就可以触发搜索按钮进行内容搜索,但由于页面上还有其它按钮,而且默认不是搜索按钮,怎样才能实现回车就触发我们的搜索 ...

  7. win8 关闭防火墙

    http://jingyan.baidu.com/article/b87fe19eddb4da5218356894.html

  8. QT 随机数生成

    下面总结了QT中随机生成的方法(仅供学习参考),分为旧方法和新方法,一般来说,旧的方法已经被抛弃,在开发新的应用中推荐使用新方法.  C++ Code  12345678910111213141516 ...

  9. 织梦漏洞可疑PHP文件/article文件夹

    常见可疑文件夹: 1:article文件夹:最近很多织梦系统网站根目录被上传article文件件,里面有很多赌博静态违法html页面,可疑直接删除,此类违法信息大部分是由于您的网站存在dedecms安 ...

  10. IE每次关闭都提示IE已停止工作

    方法一:打开IE浏览器,点击工具,选择下拉菜单中的internet选项,切换至高级选项卡标签,找到“启用第三方浏览器扩展”选项.把前面的打勾去掉: 方法二:打开IE浏览器,不管是6.0还是更高的版本这 ...