java多线程
时间:2020-03-15 09:36:38
收藏:0
阅读:48
创建方式:
方式一:继承Thread.
- 自定义一个类继承Thread类。
- 重写Thread的run方法,把自定义线程的任务代码定义在run方法上。
- 创建Thread子类的对象,并且调用start方法启动一个线程。
public class MyThread extends Thread {
public void run() {
for (int i = 0; i < 100; i++)
System.out.println(getName() + i);
}
}
// test
MyThread my1=new MyThread();//设置线程名
MyThread my2=new MyThread();
my1.setName("线程1 ");
my2.setName("线程2 ");
my1.start();
my2.start();
方式二: 实现Runnable接口。
- 自定义一个类实现Runnable接口。
- 实现Runnable接口中的run方法,把自定义线程的任务代码定义在run方法上。
- 创建Runable实现类 的对象。
- 创建Thread对象,并且把Runnable实现类的对象作为参数传递。
- 调用Thread对象的start方法开启线程。
public class DeamonDemo implements Runnable{
@Override
public void run() {
for(int i = 0;i<100;i++)
System.out.println(Thread.currentThread().getName()+"---"+i);
}
}
// test
public class DeamonTest {
public static void main(String[] args) {
DeamonDemo d = new DeamonDemo();
Thread d1 = new Thread(d);
Thread d2 = new Thread(d);
d1.start();
d2.start();
}
}
守护线程
- 设置守护线程,一旦主线程结束就结束守护线程
DeamonDemo d = new DeamonDemo();
Thread d1 = new Thread(d);
Thread d2 = new Thread(d);
d1.setDaemon(true); // 设置守护线程
d2.setDaemon(true);
d1.start();
d2.start();
for(int i = 0;i<10;i++){
//打印main线程(主线程)线程名
System.out.println(Thread.currentThread().getName()+"---"+i);
}
设置线程优先级
- IllegalArgumentException
- void setPriority()
- int getPriority():优先级范围1-10 默认5
PriorityDemo p = new PriorityDemo();
Thread tp1 = new Thread(p);
Thread tp2 = new Thread(p);
Thread tp3 = new Thread(p);
tp1.setName("xyg");
tp2.setName("wdf");
tp3.setName("OoO");
tp1.setPriority(10); // 最高优先级
tp2.setPriority(1);
tp3.setPriority(1);
tp1.start();
tp2.start();
tp3.start();
线程join
- 一旦有join()线程,其他线程必须等待
JoinDemo p = new JoinDemo();
Thread tp1 = new Thread(p);
Thread tp2 = new Thread(p);
Thread tp3 = new Thread(p);
tp1.setName("xyg");
tp2.setName("fuck");
tp3.setName("wdnmd");
tp1.setPriority(10);
tp2.setPriority(1);
tp3.setPriority(1);
tp1.start();
try {
tp1.join(); // 其他线程等待该线程终止
} catch (InterruptedException e) {
e.printStackTrace();
}
tp2.start();
tp3.start();
线程等待和唤醒
等待唤醒机制:
- wait() 让线程处于等待状态
- notify() 唤醒等待的线程
- wait()的线程被唤醒后,继续执行,wait()方法出现后,对应的线程就释放了锁对象
wait()和sleep()
- wait()是Object类方法,释放锁对象
- sleep()是Thread类的的静态方法,不释放锁对象
public synchronized void set(String name, int age) {
//如果有数据则等待
if (flag) {
try {
wait(); // 线程等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//设置值
this.name=name;
this.age=age;
// 修改标记
flag = true;
notify();// 线程唤醒
}
...
public synchronized void get(){
//如果没有数据就等待
if(!flag){
try {
wait(); // 线程等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(name+" "+age);
//修改标记
flag=false;
notify(); // 线程唤醒
}
线程暂停
- public static void yield()----Thread:暂停当前正在执行的线程,并执行其他线程
- 使用yield()的目的是让相同优先级的线程之间能适当的轮转执行。但是,实际中无法保证yield()达到让步目的
- 因为让步的线程还有可能被线程调度程序再次选中。
public void run() {
for(int i = 0;i<100;i++){
System.out.println(Thread.currentThread().getName()+"---"+i);
Thread.yield(); //执行其他线程
}
}
线程安全
1是否有共享数据
2是否多条语句操作共享数据
3是否在多线程环境中
解决方案:
- 同步代码块
synchronized(锁){
需要被同步的代码
}
...
public void run() {
if (x%2==0) {
//同步代码块
synchronized (this) {// 多个线程使用同一个锁对象
if (ticket > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在出售第" + (ticket--) + "张票。");
}
}
}
- 同步函数。
修饰符 synchronized 返回值类型 函数名(形参列表..){
需要被同步的代码
}
public void run() {
check();
}
...
//同步方法
//同步方法的锁对象是this对象
//静态同步方法的锁对象是 类名.class Class类型对象
private synchronized void check() {
if (ticket > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在出售第" + (ticket--) + "张票。");
}
}
注意:
- 同步代码块的锁可以是任意的对象。 同步函数的锁是固定 的,非静态函数的锁对象是this对象。 静态函数的锁对象是class对象。
- 锁对象必须是多线程共享的对象,否则锁不住。
- 在同步代码块或者是同步函数中调用sleep方法是不会释放锁对象的,如果是调用了wait方法是会释放锁对象的。
评论(0)