Java学习笔记44(多线程一:Thread类)
多线程的概念:略
多线程的目的:提高效率
主线程:
package demo;
//主线程
public class Demo {
public static void main(String[] args) {
function();
System.out.println(1);
} public static void function(){
for (int i = 0; i < 10000; i++) {
System.out.println(i);
}
}
}
这段简单的代码,我们发现:
必须要先执行方法输出完10000次的数字后才可以打印第二行的数字1
那么有没有方法,可以做到在执行方法的同时执行第二行的输出?
Thread类
创建新线程的两种方法:
第一种:
package demo; public class SubThread extends Thread {
//重写run方法
public void run(){
for(int i = 0 ; i< 50 ; i++){
System.out.println(i+"run");
}
}
}
package demo; public class ThreadDemo {
public static void main(String[] args) {
SubThread st1 = new SubThread();
st1.start();
for (int i = 0; i < 50; i++) {
System.out.println(i+"main");
}
}
}
这里输出时候,发现打印的run和main随机出现,交错出现,而不像以前那样按顺序打印
原因:创建了新的线程,两条线程由cpu选择执行,我们无法控制
start方法开启新的线程,继承了Thread类因为只有继承了它才可以操作线程
重写run方法因为,Thread类本身没有写入有意义的run方法,相当于一个模板,供开发者使用
线程名:
每个线程都有自己的名字,主线程名:main,其他新建线程默认名:Thread-n
获取、修改线程名:
package demo1; public class NameThread extends Thread {
public void run(){
System.out.println(super.getName());
//输出:默认是Thread-0,如果修改了,就是hello
}
}
package demo1; public class ThreadDemo {
public static void main(String[] args) {
NameThread nt1 = new NameThread();
nt1.setName("hello");
//修改线程名为hello,主线程不能改名
nt1.start(); Thread t = Thread.currentThread();
System.out.println(t.getName());
//输出:main
}
}
Thread类的一个实用方法:
package demo1; public class ThreadDemo {
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 10; i++) {
Thread.sleep(1000);
System.out.println(i);
}
//每次打印都会等待一秒,参数是毫秒值
}
}
第二种创建线程方法:
package demo1; public class SubRunnable implements Runnable {
public void run() {
for (int i = 0; i < 50; i++) {
System.out.println(i + "run");
}
}
}
package demo1; public class ThreadDemo {
public static void main(String[] args) {
SubRunnable sr1 = new SubRunnable();
Thread t1 = new Thread(sr1);
t1.start();
for (int i = 0; i < 50; i++) {
System.out.println(i + "main");
}
}
}
这种方式好处:
1.接口可以多实现,避免了单继承的局限性
2.线程和方法分离,更符合面向对象的特点
3.资源实现共享
这两种方式可以实用匿名内部类实现:
package demo1; public class ThreadDemo {
public static void main(String[] args) {
// 继承方式
new Thread() {
public void run() {
System.out.println("1");
}
}.start(); // 实现接口方式
new Thread(new Runnable() {
public void run() {
System.out.println(2);
}
}).start(); }
}
线程的状态:
1.新建状态:new Thread()创建线程对象
2.运行状态:使用了start()方法进入运行状态
3.退出状态:run方法结束,或者调用了stop方法(已过时,不建议实用)
4.阻塞状态:有时候使用了start方法,但不一定立即运行,或者运行之后CPU由于一些原因不再分配,由运行状态转到阻塞状态
5.休眠状态:前边提到的sleep方法就是这种状态,也有可能转到阻塞状态或者运行状态
6.等待状态:wait方法,无限等待,notify方法可以唤醒线程,可能转到运行或阻塞状态
注意:受阻塞是等待CPU的资源,休眠等待是放弃CPU的执行
线程池的概念:
一个容器,存入多个线程,需要时候,拿出执行,
运行结束后线程再回到容器中,这种方式可以提高效率
实现线程池:
package demo1; public class ThreadPoolRunnable implements Runnable {
public void run(){
System.out.println(Thread.currentThread().getName()+"线程提交任务");
//输出: pool-1-thread-1线程提交任务
// pool-1-thread-2线程提交任务
}
package demo1; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; public class ThreadPoolDemo {
public static void main(String[] args) {
//调用工厂类的方法创建线程池
ExecutorService es1 = Executors.newFixedThreadPool(2);
es1.submit(new ThreadPoolRunnable());
es1.submit(new ThreadPoolRunnable());
//运行后不会停 es1.shutdown();//销毁线程池,不常用
}
}
实现线程的Callable接口方式:
它弥补了Runnable方式的缺陷:无法抛出异常,并且有返回值
使用方法和Runnable方式基本一致:
示例:
package demo1; import java.util.concurrent.Callable; public class ThreadPoolCallable implements Callable<String>{
public String call(){
return "a";
}
}
package demo1; import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future; public class ThreadPoolDemo {
public static void main(String[] args) throws InterruptedException, ExecutionException {
ExecutorService es1 = Executors.newFixedThreadPool(2);
Future<String>f1 = es1.submit(new ThreadPoolCallable());
String s1 = f1.get();
System.out.println(s1);
//得到返回值,输出a
}
}
简单应用:多线程异步计算
使用两个线程计算求和:
package demo1; import java.util.concurrent.Callable; public class GetSumCallable implements Callable<Integer> {
private int a; public GetSumCallable(int a) {
this.a = a;
} public Integer call() {
int sum = 0;
for (int i = 0; i <= a; i++) {
sum += i;
}
return sum;
}
}
package demo1; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future; public class ThreadPoolDemo {
public static void main(String[] args) throws Exception {
ExecutorService es1 = Executors.newFixedThreadPool(2);
Future<Integer> f1 = es1.submit(new GetSumCallable(100));
Future<Integer> f2 = es1.submit(new GetSumCallable(300));
System.out.println(f1.get());
System.out.println(f2.get());
es1.shutdown();
}
}
Java学习笔记44(多线程一:Thread类)的更多相关文章
- Java学习笔记31(IO:Properties类)
Properties类,表示一个持久的j集,可以存在流中,或者从流中加载 是Hashtable的子类 map集合的方法都能用 用途之一:在开发项目中,我们最后交给客户的是一个编译过的class文件,客 ...
- java学习笔记6--类的继承、Object类
接着前面的学习: java学习笔记5--类的方法 java学习笔记4--类与对象的基本概念(2) java学习笔记3--类与对象的基本概念(1) java学习笔记2--数据类型.数组 java学习笔记 ...
- [core java学习笔记][第四章对象与类]
4.3 用户自定义类 4.3.1 类数组的声明 需要两次new Employee[]=staff=new Employedd[3]; staff[0]=new Employedd(参数列表); sta ...
- java学习笔记(3)——对象与类(日期)
变量.类型.赋值.运算符等等: https://blog.csdn.net/common77zwq/article/details/81988676 1.概念: 面向对象程序设计OOP.类class. ...
- 【Todo】Java学习笔记 100==100 & Reflection API & Optional类详解 & DIP、IoC、DI & token/cookie/session管理会话方式
为什么1000 == 1000返回为False,而100 == 100会返回为True? Link Java Reflection API:Link Java8 Optional 类深度解析: L ...
- Java学习笔记(2)--- 对象和类入门,java包,this 和 super区别
1.对象和类(Object and class): 一个 Java 程序可以认为是一系列对象的集合,而这些对象通过调用彼此的方法来协同工作. 面对对象编程是java非常重要的一部分,作者本身之前学过c ...
- java学习笔记15--多线程编程基础2
本文地址:http://www.cnblogs.com/archimedes/p/java-study-note15.html,转载请注明源地址. 线程的生命周期 1.线程的生命周期 线程从产生到消亡 ...
- java学习笔记14--多线程编程基础1
本文地址:http://www.cnblogs.com/archimedes/p/java-study-note14.html,转载请注明源地址. 多线程编程基础 多进程 一个独立程序的每一次运行称为 ...
- java学习笔记12--异常处理
java学习笔记系列: java学习笔记11--集合总结 java学习笔记10--泛型总结 java学习笔记9--内部类总结 java学习笔记8--接口总结 java学习笔记7--抽象类与抽象方法 j ...
随机推荐
- xtrabackup备份还原MySQL数据库
mysqldump 备份鉴于其自身的某些特性(锁表,本质上备份出来insert脚本或者文本,不支持差异备份),不太适合对实时性要求比较高的情况Xtrabackup可以解决mysqldump存在的上述的 ...
- Pushlet实现后台信息推送(一)
Pushlet是使用较多的后台向前台推送信息的工具.前台订阅某个感兴趣的事件joinListen,触发后台的Pushlet的servlet,为该请求会话建立session,默认这个sessionID是 ...
- 使用Global.asax的Application_BeginRequest事件过滤客户端XSS恶意脚本提交
XSS攻击全称跨站脚本攻击(Cross Site Scripting),是一种在web应用中的计算机安全漏洞,它允许恶意web用户将代码(如HTML代码和客户端脚本)植入到提供给其它用户使用的页面中. ...
- 【Django】网页跳转的问题
这两天有个比较奇怪了问题困扰着我,就是网页跳转之后页面没有变化,虽然url已经变了,但是页面还是原来的,只是表单数据清空了 就是http://127.0.0.1:8000/signup_signin/ ...
- 算法练习LeetCode初级算法之树
二叉树的前序遍历 我的解法:利用递归,自底向下逐步添加到list,返回最终的前序遍历list class Solution { public List<Integer> preorderT ...
- 796. Rotate String旋转字符串
[抄题]: We are given two strings, A and B. A shift on A consists of taking string A and moving the lef ...
- vba统计电脑计算机名和登陆的用户名
Public Sub GetIPT() gipt = Trim(InputBox("请输入所在组,只需输入前面的字母代码即可 A- groupA B-groupB C-groupC D-gr ...
- Python开发——【循环】语句
while循环 while 条件: # 要执行的循环体 # 如果条件为真,那么循环体则执行 # 如果条件为假,那么循环体不执行 死循环 count = 0 while True:# 条件永远为真 pr ...
- springmvc为什么是线程不安全的
1.因为springmvc默认是单例的,所以会有线程安全的问题,如果存在全局变量,因为全局变量是存在方法区的,而局部变量是放在栈中的,方法区是所有线程公用的,而每个线程都有属于自己的栈.所以如果使用单 ...
- caoni大业 spring boot 跳坑记
IDEA环境 win10 跑得刚刚,到xp系统就戈壁 报错 Caused by: java.lang.NoSuchMethodError: javax.servlet.ServletContext.g ...