java中多线程 - 多线程中的基本方法
介绍一下线程中基本的方法使用
线程睡眠sleep()
Thread.sleep(毫秒);我们可以通过sleep方法设置让线程睡眠。可以看到sleep是个静态方法
public static native void sleep(long var0) throws InterruptedException;
try {
System.out.println(new Date().getSeconds());
Thread.sleep(5000);
System.out.println(new Date().getSeconds());
} catch (InterruptedException e) {
e.printStackTrace();
}
setDaemon守护线程
非守护线程停止,那么守护线程自动退出
public static void main(String[] args) {
Thread thread1 = new Thread() {
@Override
public void run() {
super.run();
for(int i = 0; i < 5; i ++) {
System.out.println("非守护线程");
}
}
};
Thread thread2 = new Thread() {
@Override
public void run() {
for(int i = 0; i < 200; i ++) {
System.out.println("守护线程");
}
}
};
thread2.setDaemon(true);
thread1.start();
thread2.start();
}
可以很明显的看到thread2本应该执行200次输出,但是这里只输出了几行。因为当thread1执行完毕后,thread2作为守护线程就自动停止了。

多线程join
如果执行了join方法,那么停止当前线程,先跑执行了join()的线程。相当于插队执行。如下,在执行thread2线程的时候,如果i==20的时候,则让thread1插队先执行
public static void main(String[] args) {
final Thread thread1 = new Thread() {
@Override
public void run() {
super.run();
for(int i = 0; i < 500; i ++) {
System.out.println("thread1---" + i);
}
}
};
Thread thread2 = new Thread() {
@Override
public void run() {
for(int i = 0; i < 200; i ++) {
if (i == 20) {
try {
//插队执行
thread1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(i);
}
}
};
thread1.start();
thread2.start();
}
join()方法也可以传参数long 毫秒 join(毫秒)
表示让执行join的线程,插队执行XXX毫秒,过了时间后,两个线程交替执行
public static void main(String[] args) {
final Thread thread1 = new Thread() {
@Override
public void run() {
super.run();
for(int i = 0; i < 500; i ++) {
System.out.println("thread1---" + i);
}
}
};
Thread thread2 = new Thread() {
@Override
public void run() {
for(int i = 0; i < 200; i ++) {
if (i == 20) {
try {
//插队执行1毫秒
thread1.join(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(i);
}
}
};
thread1.start();
thread2.start();
}
yeild 礼让线程
yeild会让出cpu,让其他线程执行
public static void main(String[] args) {
final Thread thread1 = new Thread() {
@Override
public void run() {
super.run();
for(int i = 0; i < 500; i ++) {
System.out.println( getName() + "---" + i);
}
}
};
Thread thread2 = new Thread() {
@Override
public void run() {
for(int i = 0; i < 200; i ++) {
if (i % 5 == 0) {
Thread.yield();
}
System.out.println(getName() + "---" + i);
}
}
};
thread1.start();
thread2.start();
}
setPriority给线程设置优先级
默认优先级是5 最小1,最大10
越大优先级越高
public static void main(String[] args) {
final Thread thread1 = new Thread() {
@Override
public void run() {
super.run();
for(int i = 0; i < 500; i ++) {
System.out.println( getName() + "---" + i);
}
}
};
Thread thread2 = new Thread() {
@Override
public void run() {
for(int i = 0; i < 500; i ++) {
System.out.println(getName() + "---" + i);
}
}
};
//设置最大的线程优先级最大为10
thread1.setPriority(Thread.MIN_PRIORITY);
//设置最小的线程优先级,最小为1
thread2.setPriority(Thread.MAX_PRIORITY);
thread1.start();
thread2.start();
}
synchronized
同步代码块
当多线程并发,多段代码同时执行的时候。希望在执行其中代码的时候,cpu不切换线程
不用synchronized的情况
我们来看一下不用synchronized的情况会发生什么
public class ThreadSynchronied {
public static void main(String[] args) {
final Say say = new Say();
Thread thread1 = new Thread() {
@Override
public void run() {
for (int i = 0 ; i < 10000 ; i ++) {
say.say();
}
}
};
Thread thread2 = new Thread() {
@Override
public void run() {
for (int i = 0 ; i < 10000 ; i ++) {
say.say1();
}
}
};
//设置最大的线程优先级最大为10
thread1.setPriority(Thread.MIN_PRIORITY);
//设置最小的线程优先级,最小为1
thread2.setPriority(Thread.MAX_PRIORITY);
thread1.start();
thread2.start();
}
}
class Say {
void say() {
System.out.print("s ");
System.out.print("a ");
System.out.print("y ");
System.out.print("h ");
System.out.print("e ");
System.out.print("l ");
System.out.print("l ");
System.out.println("o");
}
void say1() {
System.out.print("1 ");
System.out.print("2 ");
System.out.print("3 ");
System.out.print("4 ");
System.out.print("5 ");
System.out.print("6 ");
System.out.print("7 ");
System.out.println("8");
}
}

我们发现有些输出并没有打印全,在执行线程thread1的过程中,cpu被thread2抢占。这种情况下,肯定是不符合我们的业务逻辑的。所以我们要保证线程执行了一个完整的方法后,cpu才会被其他线程抢占
使用synchronized
public class ThreadSynchronied {
public static void main(String[] args) {
final Say say = new Say();
Thread thread1 = new Thread() {
@Override
public void run() {
for (int i = 0 ; i < 10000 ; i ++) {
say.say();
}
}
};
Thread thread2 = new Thread() {
@Override
public void run() {
for (int i = 0 ; i < 10000 ; i ++) {
say.say1();
}
}
};
//设置最大的线程优先级最大为10
thread1.setPriority(Thread.MIN_PRIORITY);
//设置最小的线程优先级,最小为1
thread2.setPriority(Thread.MAX_PRIORITY);
thread1.start();
thread2.start();
}
}
class Say {
String s = "hahaah";
void say() {
synchronized (s) {
System.out.print("s ");
System.out.print("a ");
System.out.print("y ");
System.out.print("h ");
System.out.print("e ");
System.out.print("l ");
System.out.print("l ");
System.out.println("o");
}
}
void say1() {
synchronized (s) {
System.out.print("1 ");
System.out.print("2 ");
System.out.print("3 ");
System.out.print("4 ");
System.out.print("5 ");
System.out.print("6 ");
System.out.print("7 ");
System.out.println("8");
}
}
}

使用synchronized同步代码块后,就发现不会出现上述情况了
同步方法
public class ThreadSynchroniedMethod {
public static void main(String[] args) {
final Say say = new Say();
Thread thread1 = new Thread() {
@Override
public void run() {
for (int i = 0 ; i < 10000 ; i ++) {
say.say();
}
}
};
Thread thread2 = new Thread() {
@Override
public void run() {
for (int i = 0 ; i < 10000 ; i ++) {
say.say1();
}
}
};
//设置最大的线程优先级最大为10
thread1.setPriority(Thread.MIN_PRIORITY);
//设置最小的线程优先级,最小为1
thread2.setPriority(Thread.MAX_PRIORITY);
thread1.start();
thread2.start();
}
}
class Say {
//在方法上加锁
static synchronized void say() {
System.out.print("s ");
System.out.print("a ");
System.out.print("y ");
System.out.print("h ");
System.out.print("e ");
System.out.print("l ");
System.out.print("l ");
System.out.println("o");
}
static void say1() {
synchronized (Say.class) {
System.out.print("1 ");
System.out.print("2 ");
System.out.print("3 ");
System.out.print("4 ");
System.out.print("5 ");
System.out.print("6 ");
System.out.print("7 ");
System.out.println("8");
}
}
}
同步方法指的就是在方法上加锁
静态同步方法的所对象是该类的字节码对象
非静态的同步方法锁对象是this
多个线程使用同一资源锁,容易造成死锁
什么是死锁?
死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。
线程安全类
Vector
StringBuffer
HashTable
线程不安全
ArrayList
StringBuilder
HashSet
java.util.Collections中有synchronizedList等方法,支持我们把线程不安全的集合转成线程安全的

学习笔记
多次启动一个线程是非法的
java中多线程 - 多线程中的基本方法的更多相关文章
- Java线程和多线程(二)——对象中的wait,notify以及notifyAll方法
Java对象中的wait,notify以及notifyAll方法 在Java的Object类中包含了3个final的方法,这三个方法允许线程来交流资源是否被锁定.这三个方法就是wait(),notif ...
- java多线程中wait/notify/sleep/join/yield方法以及多线程的六种状态
刚开始学线程的时候也是被这几个方法搞的云里雾里的,尤其是一开始看的毕老师的视频,老师一直在强调执行权和执行资格,看的有点懵逼,当然不是说毕老师讲的不好,就是自己有点没听明白,后来复习看了一些其他的博客 ...
- Java多线程中join、yield、sleep方法详解
在Java多线程编程中,Thread类是其中一个核心和关键的角色.因此,对该类中一些基础常用方法的理解和熟练使用是开发多线程代码的基础.本篇主要总结一下Thread中常用的一些静态方法的含义及代码中的 ...
- 详细分析 Java 中实现多线程的方法有几种?(从本质上出发)
详细分析 Java 中实现多线程的方法有几种?(从本质上出发) 正确的说法(从本质上出发) 实现多线程的官方正确方法: 2 种. Oracle 官网的文档说明 方法小结 方法一: 实现 Runnabl ...
- Java多线程入门中几个常用的方法
一.currentThread()方法 currentThread方法就是返回当前被调用的线程. 该方法为一个本地方法,原码如下: /** * Returns a reference to the c ...
- 黑马程序员_ JAVA中的多线程
------- android培训.java培训.期待与您交流! ---------- 尽管线程对象的常用方法可以通过API文档来了解,但是有很多方法仅仅从API说明是无法详细了解的. 本来打算用一节 ...
- 【转】Java多线程编程中易混淆的3个关键字( volatile、ThreadLocal、synchronized)总结
概述 最近在看<ThinKing In Java>,看到多线程章节时觉得有一些概念比较容易混淆有必要总结一下,虽然都不是新的东西,不过还是蛮重要,很基本的,在开发或阅读源码中经常会遇到,在 ...
- java中的多线程——进度1
import java.util.*;public static void main(String[] args) {/*final可以修饰类,方法,变量.final修饰的类不可以被继承.final修 ...
- JAVA并发七(多线程环境中安全使用集合API)
在集合API中,最初设计的Vector和Hashtable是多线程安全的.例如:对于Vector来说,用来添加和删除元素的方法是同步的.如果只有一个线程与Vector的实例交互,那么,要求获取和释放对 ...
- Java多线程编程中Future模式的详解
Java多线程编程中,常用的多线程设计模式包括:Future模式.Master-Worker模式.Guarded Suspeionsion模式.不变模式和生产者-消费者模式等.这篇文章主要讲述Futu ...
随机推荐
- Matplotlib散点图、条形图、直方图-02
对比常用统计图 折线图: 特点:能够显示数据的变化趋势,反映事物的变化情况.(变化) 直方图: 特点:绘制连续性的数据,展示一组或者多组数据的分布情况(统计) 条形图: 特点:绘制离散的数据,能够一眼 ...
- python Fatal error in launcher
1.之前电脑上只安装了一个python2.7时pip install virtualenv安装了virtualenv,后来又装了py3.6.最近想做断网环境下的虚拟环境快速移植发现查看virtuale ...
- js初学总结
基础 交换变量方式 //利用第三方变量进行交换 var num1 = 10; var num2 = 20; var temp; temp = num1; num1 = num2; num2 = tem ...
- redis常用操作-键的生存时间
System.out.println("设置 key001的过期时间为5秒:"+jedis.expire("key001", 5)); System.out.p ...
- JDK 1.8 之 Map.merge()
Map 中ConcurrentHashMap是线程安全的,但不是所有操作都是,例如get()之后再put()就不是了,这时使用merge()确保没有更新会丢失. 因为Map.merge()意味着我们可 ...
- 网关我选 Spring Cloud Gateway
网关可提供请求路由与组合.协议转换.安全认证.服务鉴权.流量控制与日志监控等服务.可选的网关有不少,比如 Nginx.高性能网关 OpenResty.Linkerd 以及 Spring Cloud G ...
- Eclipse的Debug(一)
本文链接:https://blog.csdn.net/u011781521/article/details/55000066 http://blog.csdn.net/u010075335/ar ...
- Java课程作业--参数求和
一.设计思想: 这个程序是利用了参数进行输入,达到一次可以输入多个值的问题,同时输入数的个数没有限制(参数大于0个,如果为0个,应该输出提示请输入参数).本程序共分为步:1.利用参数行进行输入要加的数 ...
- 经典的Redis的主从复制搭建
##### 配置服务器 1).打开redis.conf文件修改 bind 指定的ip地址: 
Spring MVC(Model-View-Controller) 当你看到本博文时,我猜你可能正面临着我已探索过的问题. 同其他博主一样,我先按照书上详细的介绍一下 Spring MVC,也是为了自 ...