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修炼心得-DOM节点的插入
1. 内部插入append()与appendTo() append:这个操作与对指定的元素执行原生的appendChild方法,将它们添加到文档中的情况类似. appendTo:实际上,使用这个方法是 ...
- java之对数组排序
一.在运行时输入数组 import java.util.*; //也可以写成 import java.util.Scanner; public class px { public static vo ...
- Windows下主机名和IP映射设置
如果需要添加域名和IP的对应关系可以在以下地方进行修改. 打开系统目录:c:/windows/system32/drivers/etc找到hosts文件,打开hosts文件并在最后面添加一条记录 例如 ...
- Python之返回函数
高阶函数可以把函数作为一个结果值返回 举例说明 普通的求积函数是 vim day5-6.py #!/usr/bin/python # -*- coding:utf-8 -*- def product( ...
- javascript设计模式详解之命令模式
每种设计模式的出现都是为了弥补语言在某方面的不足,解决特定环境下的问题.思想是相通的.只不过不同的设计语言有其特定的实现.对javascript这种动态语言来说,弱类型的特性,与生俱来的多态性,导致某 ...
- Js之on与addEventListener的使用与两者的不同
Js之on和addEventListener的使用与不同 一.首先介绍两者的用法: 1.on的用法:以onclick为例 第一种: obj.onclick = function(){ //do som ...
- Mongodb密码安全设置
先从官网下载mongo安装包(建议安装3.0之后的版本)版本选择下载链接: https://www.mongodb.org/dl/win32/x86_64-2008plus-ssl?_ga=2.210 ...
- VR全景智慧城市-VR大时代
这是一个创业的时代,这是一个创新的社会,我们的国家从没有像今天这样高度重视创业创新,我们的社会从没有像今天这样对创业创新寄予如此厚望.李克强总理在2015年政府工作报告中指出:要把"大众创业 ...
- Spring-AOP用法总结
前言 Spring AOP的实现方法很多,在项目开发中具体采用什么方式,需要按实际情况来选择,每一种的用法,有其一定的实用价值,所以本文将各种使用方法进行了具体实现.主要包括Advice的be ...
- Android onclick监听事件打开新界面
一.新建工程 二.新建XML代码 新建一个Button <Button android:layout_width="wrap_content" android:layout_ ...