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 ...
随机推荐
- jQuery选择器与CSS选择器
1. 通过位置选择的几个操作: :first:默认情况下是相对整个页面来说的第一个,如:li:first表示整个页面的第一个li元素,而ul li:first表示整个页面的第一个li元素,并且是在ul ...
- [C#学习]1.Hello World
在很多时候我们都是被helloworld带入编程的世界的,所以这句话应该算是我们程序员最熟悉的一句话了把.所以在这里,那我也照样以helloworld为例子来引入我们的C#学习. 在往常的hellow ...
- hdu1083二分图匹配模板题
onsider a group of N students and P courses. Each student visits zero, one or more than one courses. ...
- 微信小程序(兼容性问题)
兼容 小程序的功能不断的增加,但是旧版本的微信客户端并不支持新功能,所以在使用这些新能力的时候需要做兼容. 文档会在组件,API等页面描述中带上各个功能所支持的版本号. 可以通过 wx.getSyst ...
- 原创-angularjs2不同组件间的通信
AngualrJs2官方方法是以@Input,@Output来实现组件间的相互传值,而且组件之间必须父子关系,下面给大家提供一个简单的方法,实现组件间的传值,不仅仅是父子组件,跨模块的组件也可以实现传 ...
- GitHub的实践
GitHub的实践 2017-05-08,晴,来小米已经一周的时间了,感谢领导能给我一周的时间来熟悉 ubuntu.spring boot.maven.docker.github .大家会问,这些不都 ...
- poj1011 搜索+剪枝
DFS+剪枝 POJ2362的强化版,重点在于剪枝 令InitLen为所求的最短原始棒长,maxlen为给定的棒子堆中最长的棒子,sumlen为这堆棒子的长度之和,那么InitLen必定在范围[max ...
- 区块链入门(1):搭建(Ubuntu系统)Truffle v3.2.1 开发和测试环境
本文主要讲解ubuntu 16.04下, truffle开发测试环境的搭建. 第一步:安装nodejs 和 npm,有两种比较常见的方法. 方法1:直接在nodejs官网下载nodejs-v6.10 ...
- 最牛分布式消息系统:Kafka
Kafka是分布式发布-订阅消息系统.它最初由LinkedIn公司开发,之后成为Apache项目的一部分.Kafka是一个分布式的,可划分的,冗余备份的持久性的日志服务.它主要用于处理活跃的流式数据. ...
- Lua学习(1)——table
table类型实现了“关联数组”.“关联数组”是一种具有特殊索引方式的数组.不仅可以通过证书来索引它,还可以使用字符串或其他类型(除了nil)来索引它.table是Lua中主要的数据结构机制(事实也是 ...