多线程中的常用成员方法
String getName() 返回此线程的名称
void setName(String name) 设置线程的名称 (构造方法也可以设置名称)
static Thread currentThread() 获取当前线程的对象
static void sleep(long time) 让当前线程休眠指定的毫秒数
setPriority(int newPriority) 设置线程的优先级*
final int getPriority()* 获取线程的优先级
package xyz.dimeng.m04threadmethod1;
public class MyThread extends Thread{
public MyThread() {
}
public MyThread(String name) {
super(name);
}
@Override
public void run() {
for (int i = 0; i <= 100; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(getName()+"-"+i);
}
}
}
package xyz.dimeng.m04threadmethod1;
public class ThreadDemo {
public static void main(String[] args) throws InterruptedException {
/***
* String getName() 返回此线程的名称
* void setName(String name) 设置线程的名称 (构造方法也可以设置名称)
* 1.如果我们没有给线程设置名称,线程也是有默认的名字的 格式:Thread-X (X序号,从0开始)
* 2.如果我们要给线程设置名字 可以用set方法设置也可以用构造方法设置
*
* static Thread currentThread() 获取当前线程的对象
* 当jvm虚拟机启动之后,会自动的启动多条线程
* 其中有一条线程就叫main线程 作用就是调用main方法并执行里面的代码
* static void sleep(long time) 让当前线程休眠指定的毫秒数
*/
MyThread t1 = new MyThread("main");
MyThread t2 = new MyThread("sub");
t1.start();
t2.start();
// Thread t = Thread.currentThread();
// String name = t.getName();
// System.out.println(name);
// System.out.println("---------");
// Thread.sleep(5000);
// System.out.println("=============");
}
}
package xyz.dimeng.m05threadmethod2;
public class MyRunnable implements Runnable{
@Override
public void run() {
for (int i = 0; i <= 100; i++) {
System.out.println(Thread.currentThread().getName()+"-"+i);
}
}
}
package xyz.dimeng.m05threadmethod2;
public class ThreadDemo {
public static void main(String[] args) throws InterruptedException {
/***
* setPriority(int newPriority) 设置线程的优先级
* final int getPriority() 获取线程的优先级
* 不是绝对的 概率问题
*/
MyRunnable mr = new MyRunnable();
Thread t1 = new Thread(mr,"main");
Thread t2 = new Thread(mr,"sub");
/*System.out.println(t1.getPriority());
System.out.println(t2.getPriority());
System.out.println(Thread.currentThread().getPriority());*/
t1.setPriority(1);
t2.setPriority(10);
t1.start();
t2.start();
}
}
final void setDaemon(boolean on) 设置为守护线程
package xyz.dimeng.m06threadmethod3;
public class ThreadDemo {
public static void main(String[] args){
/***
* final void setDaemon(boolean on) 设置为守护线程
* 当其他的非守护线程执行完毕之后,守护线程会陆续结束
* (应用场景 聊天时候传输文件 传输文件的线程设置为守护线程)
*/
MyThread1 t1 = new MyThread1();
MyThread2 t2 = new MyThread2();
t1.setName("sub");
t2.setName("main");
t2.setDaemon(true);
t1.start();
t2.start();
}
}
package xyz.dimeng.m06threadmethod3;
public class MyThread1 extends Thread{
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(getName()+"-"+i);
}
}
}
package xyz.dimeng.m06threadmethod3;
public class MyThread2 extends Thread{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(getName()+"-"+i);
}
}
}
public static void yield() 出让线程*/*礼让线程
public final void join() 插入线程*/*插队线程
线程的生命周期
线程的安全问题
案例:火车站卖100张票 三个窗口
在Java中,synchronized关键字用于实现同步,确保多个线程不会同时访问共享资源,从而避免竞态条件和数据不一致性的问题。当使用synchronized关键字时,可以指定一个对象作为锁。在这种情况下,当一个线程获得了该对象的锁时,其他线程就无法同时获得该对象的锁,从而确保了同步。
在Java中,每个类在内存中都有一个对应的Class对象,而且每个类的Class对象在整个JVM中都是唯一的。因此,使用类的字节码对象作为锁对象是安全的,因为它是唯一的,可以确保在多线程环境下的同步。
package xyz.dimeng.m09threadsafe1;
public class MyThread extends Thread{
//表示这个类所有的对象,都共享ticket数据
static int ticket = 0;
//锁对象,一定是唯一的
static Object obj = new Object();
@Override
public void run() {
while (true){
//同步代码块
//synchronized (obj){
synchronized (MyThread.class){
if(ticket<100){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
ticket++;
System.out.println(getName()+"正在卖第"+ticket+"张票");
}else {
break;
}
}
}
}
}
package xyz.dimeng.m09threadsafe1;
public class ThreadDemo {
public static void main(String[] args) {
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
MyThread t3 = new MyThread();
t1.setName("窗口1");
t2.setName("窗口2");
t3.setName("窗口3");
t1.start();
t2.start();
t3.start();
}
}
单线程不需要考虑线程安全用StringBuilder
多线程用StingBuffer
同步方法
就是把synchronized关键字加到方法上
特点1:同步方法是锁住方法里面所有的代码
特点2:锁对象不能自己指定(非静态:this,静态:当前类的字节码文件对象)
package xyz.dimeng.m10threadsafe2;
import xyz.dimeng.m09threadsafe1.MyThread;
public class ThreadDemo {
public static void main(String[] args) {
//利用同步方法完成保证多线程安全
MyRunnable mr = new MyRunnable();
Thread t1 = new Thread(mr);
Thread t2 = new Thread(mr);
Thread t3 = new Thread(mr);
t1.setName("窗口1");
t2.setName("窗口2");
t3.setName("窗口3");
t1.start();
t2.start();
t3.start();
}
}
package xyz.dimeng.m10threadsafe2;
public class MyRunnable implements Runnable {
int ticket = 0;
@Override
public void run() {
//1.循环
//2.同步代码块(同步方法)
//3.判断共享数据是否到了末尾,如果到了末尾
//4.判断共享数据是否到了末尾,如果没有到末尾
while (true) {
if (method()) {
break;
}
}
}
//非静态 锁对象 this
private synchronized boolean method() {
if (ticket == 100) {
return true;
} else {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
ticket++;
System.out.println(Thread.currentThread().getName() + "在卖:" + ticket + "张票");
}
return false;
}
}