Thread初探
Thread初探
前言
以前大家写的都是单线程的程序,全是在main函数中调用方法,可以清楚的看到它的效率是特别低的,就像python中使用单线程取爬一个网站,可以说能让你等的吐血,因为数据量实在太大了,今天我们就来看看java的并发编程多线程的学习
创建线程
创建一个线程可以有多种方法,比如继承Thread类,实现Runnable接口......下面我们来详细的看看创建的方法
继承Thread
为什么继承
Thread可以直接调用start()方法启动线程呢,因为start()本身就是Thread的方法,也就是继承了Thread的start()方法,因此这个类的对象可以调用start()启动线程
//继承Thread
public class MyThread extends Thread {
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(this.getName()+"正在跑");
}
}
}
public class Test{
public static void main(String[] args)
{
Mythread t1=new MyThread(); //创建对象
t1.start(); //启动线程
}
}
注意: 继承
Thread类的创建方法一个对象只能创建一个线程,并不能多个线程共用一个对象,只能一个线程对应一个对象,因此我们来看看实现Runnable接口的类来实现多个线程共享同一个对象
实现Runnable接口
//实现Runnable接口
public class Demo implements Runnable {
@Override
public void run() {
for(int i=0;i<10;i++)
{
System.out.println(Thread.currentThread().getName()+"正在跑");
}
}
}
//测试类
public class Test{
public static void main(String[] args)
{
Demo d=new Demo(); //创建对象
Thread thread1=new Thread(d); //为对象创建一个线程
Thread thread2=new Thread(d); //创建另外一个线程
//同时启动两个线程
thread1.start();
thread2.start();
}
}
从上面可以清楚的看到实现
Runnable接口的类一个对象可以供多个线程共享,并不像继承Thread类只为一个线程使用
简便的创建方法
直接在
main方法中创建,如果创建的普通类的对象在外面,那么必须是final修饰,可以实现多个线程同时共享一个对象,这个和实现Runnable接口一样,这时候就要控制同步条件了,如果在run方法中定义对象,那么,就是一个线程对应一个对象,这个就和继承Thread类一样的效果。所以可以根据条件自由选择
//普通的一个类
public class Simple {
public void display()
{
for(int i=0;i<10;i++)
{
System.out.println(Thread.currentThread().getName()+"正在跑");
}
}
}
//线程测试类
public class Test {
public static void main(String[] args) {
//如果在外面必须使用final,当然也可以直写在run方法中,不过写在外面可以实现多个线程共享一个对象
//写在run方法中当前对象只能为一个线程使用,和继承Thread类一样的效果
final Simple simple=new Simple();
//下面创建使用同一个对象创建同两个线程,实现多个线程共享一个对象,和实现Runnable接口一样的效果
Thread t1=new Thread(){
public void run() {
simple.display();
};
};
Thread t2=new Thread(){
public void run() {
simple.display();
};
};
//启动这两个线程
t1.start();
t2.start();
}}
常用的方法
static void sleep(long mils)使正在运行的线程休眠mils毫秒,但是这里需要注意的是如果线程加了锁,那么使线程休眠并不会释放锁
String getName()得到线程的名称,上面的程序中已经使用了这个方法
void setName(String name)设置正在运行的线程的名字为name
start()启动线程,线程的创建并不意味着线程的启动,只有调用start()方法线程才是真正的开始运行
long getId()返回线程的标识符
run()线程执行的代码都放在run()方法中,在run方法中的调用是有序的,都是按照程序运行的顺序开始执行
使用
下面使用上面的方法创建一个实例
//线程的类,继承Thread
public class MyThread1 extends Thread {
public void run() { // 重载run方法,并且在其中写线程执行的代码块
for (int i = 0; i < 10; i++) {
// 获取线程的id和name
System.out.println("Thread-Name: " + this.getName()
+ " Thread-id: " + this.getId());
try {
this.sleep(1000); // 线程休眠1秒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//线程测试的类
public class Test {
public static void main(String[] args) {
MyThread1 t1 = new MyThread1(); // 创建线程
t1.setName("第一个线程"); // 设置线程的名字
MyThread1 t2 = new MyThread1();
t2.setName("第二个线程");
t1.start(); // 启动线程,开始运行
t2.start();
}
}
void join()等待该线程终止才能运行其他的线程void join(long mils)等待该线程的时间为mils毫秒,一旦过了这个时间其他线程正常执行
使用
//线程类
public class MyThread1 extends Thread {
public void run() { // 重载run方法,并且在其中写线程执行的代码块
for (int i = 0; i < 10; i++) {
// 获取线程的id和name
System.out.println("Thread-Name: " + this.getName()
+ " Thread-id: " + this.getId());
try {
this.sleep(1000); // 线程休眠1秒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//测试类
public class Test {
public static void main(String[] args) {
MyThread1 t1 = new MyThread1(); // 创建线程
t1.setName("第一个线程"); // 设置线程的名字
t1.start(); // 启动线程,开始运行
try {
t1.join(); //阻塞其他线程,只有当这个线程运行完之后才开始运行其他的线程
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < 10; i++) {
System.out.println("主线程正在运行");
}
}
}
//输出结果
/*
Thread-Name: 第一个线程 Thread-id: 9
Thread-Name: 第一个线程 Thread-id: 9
Thread-Name: 第一个线程 Thread-id: 9
Thread-Name: 第一个线程 Thread-id: 9
Thread-Name: 第一个线程 Thread-id: 9
Thread-Name: 第一个线程 Thread-id: 9
Thread-Name: 第一个线程 Thread-id: 9
Thread-Name: 第一个线程 Thread-id: 9
Thread-Name: 第一个线程 Thread-id: 9
Thread-Name: 第一个线程 Thread-id: 9
主线程正在运行
主线程正在运行
主线程正在运行
主线程正在运行
主线程正在运行
主线程正在运行
主线程正在运行
主线程正在运行
主线程正在运行
主线程正在运行
*/
getPriority()得到当前线程优先级setPriority(int num)更改线程的优先级(0-10)默认的是5,优先级越高获得cpu资源的几率就会越高
使用
//线程类
public class MyThread1 extends Thread {
public void run() { // 重载run方法,并且在其中写线程执行的代码块
for (int i = 0; i < 10; i++) {
// 获取线程的id和name
System.out.println("Thread-Name: " + this.getName()
+ " Thread-id: " + this.getId());
try {
this.sleep(1000); // 线程休眠1秒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//测试类
public class Test {
public static void main(String[] args) {
MyThread1 t1 = new MyThread1(); // 创建线程
t1.setName("第一个线程"); // 设置线程的名字
MyThread1 t2 = new MyThread1();
t2.setName("第二个线程");
t2.setPriority(8); //设置第二个线程的优先级为8,第一个线程的优先级为5(是默认的)
t1.start();
t2.start();
}
}
/*
* 从上面的运行结果可以看出大部分的第二个线程都是在第一个线程之前开始执行的,也就是说优先级越高获得cpu执行的几率就越大
* /
setDaemon(boolean)是否设置为守护线程,如果设置为守护线程,那么主线程销毁守护线程也会随之销毁isDaemon()判断是否为守护线程
使用
//测试类
public class MyThread1 extends Thread {
public void run() { // 重载run方法,并且在其中写线程执行的代码块
for (int i = 0; i < 10; i++) {
// 获取线程的id和name
System.out.println("Thread-Name: " + this.getName()
+ " Thread-id: " + this.getId());
try {
Thread.sleep(1000); //休眠一秒,方便主线程运行结束
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Test {
public static void main(String[] args) {
MyThread1 t1 = new MyThread1(); // 创建线程
t1.setName("第一个线程"); // 设置线程的名字
t1.setDaemon(true);
t1.start();
for (int i = 0; i < 1; i++) {
System.out.println(i);
}
}
}
//结果:
/*
0
1
2
3
4
5
6
7
8
9
Thread-Name: 第一个线程 Thread-id: 9
*/
/*
* 从上面的结果可以看出,一旦主线程结束,那么守护线程就会自动的结束
* /
参考文章
Thread初探的更多相关文章
- Thread线程初探
using System; using System.Threading; class Example { static void Main() { TimeSpan interval = , , ) ...
- .NET文件并发与RabbitMQ(初探RabbitMQ)
本文版权归博客园和作者吴双本人共同所有.欢迎转载,转载和爬虫请注明原文地址:http://www.cnblogs.com/tdws/p/5860668.html 想必MQ这两个字母对于各位前辈们和老司 ...
- NoSQL初探之人人都爱Redis:(3)使用Redis作为消息队列服务场景应用案例
一.消息队列场景简介 “消息”是在两台计算机间传送的数据单位.消息可以非常简单,例如只包含文本字符串:也可以更复杂,可能包含嵌入对象.消息被发送到队列中,“消息队列”是在消息的传输过程中保存消息的容器 ...
- 初探asp.net异步编程之await
终于毕业了,也顺利进入一家期望的旅游互联网公司.27号入职.放肆了一个多月没写代码,好方啊. 另外一下观点均主要针对于await. 请先看这段话,来自async in C# 5.0. 接下来几个月的 ...
- WCF初探-28:WCF中的并发
理解WCF中的并发机制 在对WCF并发机制进行理解时,必须对WCF初探-27:WCF中的实例化进行理解,因为WCF中的并发特点是伴随着服务实例上下文实现的.WCF的实例上下文模型可以通过Instanc ...
- Java Lambda表达式初探
Java Lambda表达式初探 前言 本文受启发于Trisha Gee在JavaOne 2016的主题演讲Refactoring to Java 8. Java 8已经发行两年多,但很多人仍然在使用 ...
- 【转】NoSQL初探之人人都爱Redis:(3)使用Redis作为消息队列服务场景应用案例
一.消息队列场景简介 “消息”是在两台计算机间传送的数据单位.消息可以非常简单,例如只包含文本字符串:也可以更复杂,可能包含嵌入对象.消息被发送到队列中,“消息队列”是在消息的传输过程中保存消息的容器 ...
- WCF初探-11:WCF客户端异步调用服务
前言: 在上一篇WCF初探-10:WCF客户端调用服务 中,我详细介绍了WCF客户端调用服务的方法,但是,这些操作都是同步进行的.有时我们需要长时间处理应用程序并得到返回结果,但又不想影响程序后面代码 ...
- mysql performance_schema 初探
mysql performance_schema 初探: mysql 5.5 版本 新增了一个性能优化的引擎: PERFORMANCE_SCHEMA 这个功能默认是关闭的: 需要设置参数: perf ...
随机推荐
- JSP动态员工登陆案例
package web; import java.io.IOException; import java.io.PrintWriter; import java.util.List; import j ...
- angularjs 路由模块
1. <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title& ...
- JDK的下载与配置
一.下载JDK 1.进入oracle官网 下载完成后直接运行就能生成jdk文件. 二.配置环境 1.打开环境配置 右击计算机选择属性 选择高级系统数据 点击环境变量 2.配置JAVA_HOME 新建一 ...
- Day4 函数、列表生成式、生成器、迭代器
温故而知新: 1. 集合 主要作用: 去重 关系测试, 交集\差集\并集\反向(对称)差集 2. 元组 只读列表,只有count, index 2 个方法 作用:如果一些数据不想被人修改, 可以存成元 ...
- 单片机IAP学习
1.IAP是什么--简介 IAP是In Application Programming的首字母缩写,IAP是用户自己的程序在运行过程中对User Flash的部分区域进行烧写,目的是为了在产品发布后可 ...
- 【JAVAWEB学习笔记】08_MySQL&JDBC回顾
今天晨读单词: CRUD:增删改查(create/read/update/delete)create:新增项目read:查询update:修改delete:删除 desc 表名:查看表结构drop:删 ...
- 同步文件的利器-rsync
即使你只是个人用户而不是一个企业,备份你自己的数据也是非常重要的,我不想失去任何这些数据. rsync是同步文件的利器,一般用于多个机器之间的文件同步与备份,同时也支持在本地的不同目录之间互相同步文件 ...
- convertView的疑问(软件管理器)
package com.hixin.appexplorer; import java.util.List; import android.app.Activity; import android.co ...
- Ultimus BPM 制药与医疗行业应用解决方案
Ultimus BPM 制药与医疗行业应用解决方案 行业应用需求 制药与医疗行业客户特点有企业总资产高.员工规模大,销售网络往往遍及全国,乃至全球市场:拥有复杂的制药生产或医疗服务组织机构,并均有严格 ...
- 【css3网页布局】flex盒子模型
1.0 前言 网页布局(layout)是CSS的一个重点应用. 经典布局类型: 布局的传统解决方案,基于盒状模型,依赖 display属性 + position属性 + float属性.它对于那些特殊 ...