一、多线程的创建

1.作用

  程序需要同时执行两个或多个任务时需要多线程。

  程序需要实现需要等待的任务时,如用户输入、文件读写操作、网络操作、搜索等,需要多线程。

  需要一些后台运行的程序时,需要多线程。

2.实现

  Java语言的JVM允许程序运行多个线程,它通过java.lang.Thread来实现。

  Thread类的特性:

    每个线程都是通过某个特定Thread对象的run()方法来完成操作的。经常把run()方法的主体称为线程体。

    通过Thread对象的start()方法来启动这个线程。

3.创建多线程的第一种方法:继承java.lang.Thread类

  代码案例

  创建一个子线程,完成1-100的自然数的输出,主线程也做同样操作。

//1.创建一个继承thread的子类
class SubThread extends Thread{
//2.重写run()方法,方法体实现子线程要完成的功能
@Override
public void run(){
for(int i = ;i <= ;i++){
System.out.println(Thread.currentThread().getName()+":"+i);
//输出结果:Thread-0:1...,和主线程的输出结果交错出现。
}
}
} public class Test{
public static void main(String[] args){
//3.创建一个子类的对象,一个对象对应一个子线程
SubThread st = new SubThread(); //4.调用线程的start()方法,启动此线程,将自动调用run()方法
//一个线程只能执行一次start()
//不能通过run()方法去启动一个线程,即st.run()。
st.start(); for(int i = ;i <= ;i++){
System.out.println(Thread.currentThread().getName()+":"+i);
//输出结果:main:1...
}
} }

4.Thread的常用方法

start():启动线程并执行相应的run()方法

run():子线程要执行的代码放入到run()方法中

currentThread():静态的,调取当前的线程

getName():获取此线程的名字

setName():设置此线程的名字

yield():调用此方法的线程释放当前CPU的执行权

join():在A线程中调用B线程的join()方法:A线程停止执行,直到B线程执行完毕,A线程再接着join()之后的代码执行

isAlive():判断当前线程是否存活

sleep(long l):显式的让当前线程睡眠 l 毫秒

线程通信:wait()  notify()  notifyAll()  日后再表

getPriority():返回线程优先级,优先级从1到10十个档次,默认为5.(优先级只是抢到CPU的概率的大小区别,并不是优先级大的线程就一定先完成。)

setPriority(int newPriority):改变线程的优先级

class SubThread extends Thread{
@Override
public void run(){
for(int i = ;i <= ;i++){ //注意这里的异常处理只能是try-catch,不能throws,因为不能比父类Thread的run()方法抛出更大的异常。
try{
Thread.currentThread().sleep();//睡眠0.1秒
}catch(InterruptedException e){
e.printStackTrace();
}
//输出结果:子线程:10:1 ...
System.out.println(Thread.currentThread().getName()+":"+Thread.currentThread().getPriority()+":"+i); }
}
} public class Test{
public static void main(String[] args){ SubThread st = new SubThread();
st.setName("子线程");
//设置优先级(MIN_PRIORITY = 1 NORM_PRIORITY = 5 MAX_PRIORITY = 10)
st.setPriority(Thread.MAX_PRIORITY);
st.start();
Thread.currentThread().setName("---主线程");
for(int i = ;i <= ;i++){
//输出结果:---主线程:5:1 ... 默认优先级为5
System.out.println(Thread.currentThread().getName()+":"+Thread.currentThread().getPriority()+":"+i);
//如果i是10的整数倍,主线程调用yield,释放CPU执行权,但有可能又被主线程抢回CPU,继续执行主线程
//if(i % 10 == 0){
// Thread.currentThread().yield();
//} //如果i等于20,停止主线程的执行,直到子线程执行完毕再继续执行之后的代码。
if(i == ){
try{
st.join();
}catch(InterruptedException e){
e.printStackTrace();
} }
}
System.out.println(st.isAlive());//输出false,子进程死亡;输出true,子线程存活,比主进程慢完成
} }

5.继承方式实现多窗口售票

class Window extends Thread{
static int ticket = ;
public void run(){
while(true){
if(ticket > ){
System.out.println(Thread.currentThread().getName()+"售票,票号为:" + ticket--);
}else{
break;
}
}
}
} public class Test{
public static void main(String[] args){
Window w1 = new Window();
Window w2 = new Window();
Window w3 = new Window(); w1.setName("售票口1");
w2.setName("售票口2");
w3.setName("售票口3"); w1.start();
w2.start();
w3.start();
}
}

6.创建多进程的第二种方法:实现Runnable接口

优点(相对于继承Thread类)

  避免了Java单继承的局限性。

  如果多个线程操作同一份资源,更适合使用实现的方式(详见售票口案例的比较)

代码案例

//1.创建一个实现了Runnable接口的类
class PrintNum implements Runnable{
//2.实现接口的抽象方法run()
public void run(){
for(int i = ;i <= ;i++){
if(i % == )
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
} public class Test{
public static void main(String[] args){
//3.创建一个Runnable接口实现类的对象
PrintNum p = new PrintNum();
//4.将此对象作为形参传给Thread类的构造器中,创建Thread类的对象
Thread t1 = new Thread(p);
t1.start();//启动线程,执行Thread对象生成时构造器形参的对象的run()方法
}
}

7.实现方式实现多窗口售票

class Window implements Runnable{
int ticket = ;//注意不用static了,因为只需要创建一个对象
public void run(){
while(true){
if(ticket > ){
System.out.println(Thread.currentThread().getName()+"售票,票号为:" + ticket--);
}else{
break;
}
}
}
} public class Test{
public static void main(String[] args){
Window w = new Window();
Thread t1 = new Thread(w);
Thread t2 = new Thread(w);
Thread t3 = new Thread(w); t1.setName("售票口1");
t2.setName("售票口2");
t3.setName("售票口3"); t1.start();
t2.start();
t3.start();
}
}

  

Java语法基础学习DaySixteen(多线程)的更多相关文章

  1. Java语法基础学习DaySeventeen(多线程续)

    一.线程的特点 1.线程的分类 java中的线程分为两类:守护线程和用户线程.唯一的区别是判断JVM何时离开. 守护线程是用来服务用户线程的,通过在start()方法前调用Thread.setDaem ...

  2. Java语法基础学习DayEighteen(常用类)

    一.String类 1.特点 String代表不可变的字符序列,底层用char[]存放. String是final的. 2.内存解析 3.常用方法 int length() char charAt(i ...

  3. Java语法基础学习DaySeven

    ---恢复内容开始--- 一.包装类——Wrapper 1.定义:针对八种基本数据类型定义相应的引用类型——包装类(封装类) boolean——Boolean          byte——Byte ...

  4. Java语法基础学习DaySix

    一.JavaBean——可重用组件 1.JavaBean是指符合以下标准的Java类: (1)类是公共的 (2)有一个无参的公共的构造器 (3)有属性,且有对应的get.set方法 2.好处 用户可以 ...

  5. Java语法基础学习DayThree

    一.流程控制语句补充 1.switch语句 格式: switch(表达式) { case 值1: 语句体1; break; case 值2: 语句体2; break; ... default: 语句体 ...

  6. Java语法基础学习DayTwentyOne(网络编程)

    一.IP地址和端口号 1.作用 通过IP地址,唯一的定位互联网上一台主机. 端口号标识正在计算机上运行的进程,不同进程有不同的端口号,被规定为一个16位的整数0~65535,其中0~1023被预先定义 ...

  7. Java语法基础学习DayTwenty(反射机制续)

    一.Java动态代理 1.代理设计模式的原理 使用一个代理将对象包装起来, 然后用该代理对象取代原始对象. 任何对原始对象的调用都要通过代理. 代理对象决定是否以及何时将方法调用转到原始对象上. 2. ...

  8. Java语法基础学习DayNineteen(反射机制)

    一.Refection定义 1.概述 Reflection(反射)是被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性 ...

  9. Java语法基础学习DayFifteen(IO续)

    一.缓冲流(处理流的一种) 1.作用:可以提高文件操作的效率 2.使用BufferedInputStream和BufferedOutputStream实现非文本文件的复制 特点:flush()方法 代 ...

随机推荐

  1. zw·10倍速大数据与全内存计算

    zw·10倍速大数据与全内存计算 zw全内存10倍速计算blog,早就在博客园机器视觉栏目发过,大数据版的一直挂着,今天抽空补上. 在<零起点,python大数据与量化交易>目录中 htt ...

  2. 鼠标右键vsCode打开

    有时候在安装vscode不会出现鼠标右键用vscode打开的情况: 最终要实现的样子: 解决办法如下步骤: 1.安装vscode: 2.新建一个“.reg”为后缀的文件: 3.把下面内容复制到文件中: ...

  3. 01:golang开发环境

    1.1 go环境安装 1.go下载安装 官方:https://golang.org/dl 国内: https://golang.google.cn/dl/ https://www.golangtc.c ...

  4. 【linux下查看文件路径--jdk】

    1.which java 首先输入命令行,查看结果: [root@localhost ~]# which java /usr/bin/java PS:which Java是无法定位到Java的安装路径 ...

  5. 【Entity Framework】Model First Approach

    EF中的model first 所谓mf, 就是使用vs提供的edm designer去设计model,然后将设计好的model使用vs在指定的数据库中生成数据库即可. 当你的项目既没有数据库也没有c ...

  6. Mac OS X 清除DNS缓存

    参考: Flushing your DNS cache in Mac OS X and Linux Mac OS X 清除DNS缓存 根据Mac OS X操作系统的版本选择以下命令: Mac OS X ...

  7. kod 编辑器下载

    链接: https://pan.baidu.com/s/1ZACwJZ_x2ZBziqPlm17z6w 提取码: 3w9m

  8. 一: DRF web应用框架基础,及序列化器的使用

    ---恢复内容开始--- 一: web 应用模式(有两种) 1: 前后端不分离(前端从后端直接获取数据) 2: 前后端分离 二: api 接口 原因一: 为了在团队内部形成共识.防止个人习惯差异引起的 ...

  9. inline-block间隙问题总结, ,style一个样式后面 多加了一个 分号; 导致 样式失效

    1--- 样式最后的{}后面, 不能有分号 ; 2---- display:inline-block 后, 元素间会有间隙    原因:  由换行或者回车导致的. 解决一: 只要把标签写成一行或者标签 ...

  10. 聊聊Flume和Logstash的那些事儿

    在某个Logstash的场景下,我产生了为什么不能用Flume代替Logstash的疑问,因此查阅了不少材料在这里总结,大部分都是前人的工作经验下,加了一些我自己的思考在里面,希望对大家有帮助. 本文 ...