Java-多线程1

进程和线程

串行和并行
串行:串行是指多个任务时各个任务执行,完成一个之后才能完成下一个
并行:并行是指多个任务可以同时执行,异步是多个任务并行的前提条件

并行和并发
并行:多个cpu实例或者多台机器同时执行一段处理逻辑,是真正的同时
并发:通过cpu调度算法,让用户看起来同时执行,实际上从cpu操作层面不是真正的同时

进程和线程在这里插入图片描述
线程状态
在这里插入图片描述

初始(NEW):新创建了一个线程对象,但还没有调用start()方法。
运行(RUNNABLE):Java线程中将就绪(ready)和运行中(running)两种状态笼统的称为“运行”。
阻塞(BLOCKED):表示线程阻塞于锁。
等待(WAITING):进入该状态的线程需要等待其他线程做出一些特定动作(通知或中断)。
超时等待(TIMED_WAITING):该状态不同于WAITING,它可以在指定的时间后自行返回。
终止(TERMINATED):表示该线程已经执行完毕。

线程对象

线程定义

实现Runnable接口:提供一个Runnable对象。该 Runnable接口定义了一个方法,run用于包含在线程中执行的代码。该Runnable对象将传递给Thread构造函数

public class HelloRunnable implements Runnable {
public void run() {
System.out.println("HelloRunnable");
}
public static void main(String args[]) {
Runnable runnable = new HelloRunnable();
Thread thread = new Thread(runnable);
thread.start();
}
}

继承Thread类:子类Thread,在Thread类自身实现Runnable,但其run方法不起作用。应用程序可以子类Thread提供自己的实现run。

public class HelloThread extends Thread {
public void run() {
System.out.println("HelloThread");
}
public static void main(String args[]) {
HelloThread helloThread = new HelloThread();
helloThread.start();
}
}

线程命名
Runnable接口

public class HelloRunnableName implements Runnable {
@Override
public void run() {
System.out.println("你好: " + Thread.currentThread().getName());
}
public static void main(String[] args) {
HelloRunnableName helloRunnable = new HelloRunnableName();
Thread thread = new Thread(helloRunnable, "线程1");
System.out.println("线程名称: " + thread.getName());
thread.start();
}
}

Thread

public class HelloThreadName extends Thread {
public HelloThreadName(String name) {
// super(name);
this.setName(name);
}
@Override
public void run() {
super.run();
System.out.println("你好: " + Thread.currentThread().getName());
}
public static void main(String[] args) {
HelloThreadName helloThreadName = new HelloThreadName("线程1");
System.out.println("线程名称: " + helloThreadName.getName());
helloThreadName.start();
}
}

线程优先级
线程优先级的范围是1~10,默认的优先级是5。 10极最高。
“高优先级线程”被分配CPU的概率高于“低优先级线程”。

public class ThreadPriority implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("线程名称: "
+ Thread.currentThread().getName()
+ ",线程优先级: "
+ Thread.currentThread().getPriority()
+ ",循环: " + i);
}
}
public static void main(String[] args) {
ThreadPriority threadPriority = new ThreadPriority();
Thread thread1 = new Thread(threadPriority);
thread1.setName("线程1");
thread1.setPriority(Thread.MIN_PRIORITY);
Thread thread2 = new Thread(threadPriority);
thread2.setName("线程2");
thread2.setPriority(Thread.MAX_PRIORITY);
thread1.start();
thread2.start();
}
}

线程休眠sleep方法
Thread.sleep使当前线程在指定时间段内暂停执行。这是使处理器时间可用于应用程序的其他线程或计算机系统上可能正在运行的其他应用程序的有效方法。

public class ThreadSleep implements Runnable {
@Override
public void run() {
String info[] = {
"1",
"2",
"3",
"4"
};
for (int i = 0; i < info.length; i++) {
System.out.println(info[i]);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
ThreadSleep threadSleep = new ThreadSleep();
Thread thread = new Thread(threadSleep);
thread.start();
}
}

线程礼让yield方法

Thread类中提供了一种礼让方法,使用yield()方法表示,它只是给当前正处于运行状态下的线程一个提醒,告知它可以将资源礼让给其他线程,但这仅仅是一种暗示,没有任何一种机制保证当前线程会将资源礼让。yield()方法使具有同样优先级的线程有进入可执行状态的机会,当当前线程放弃执行权时会再度回到就绪状态。

public class ThreadYield implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "开始了");
Thread.yield();
System.out.println(Thread.currentThread().getName() + "结束了");
}
public static void main(String[] args) {
ThreadYield threadYield = new ThreadYield();
Thread thread1 = new Thread(threadYield, "线程1");
Thread thread2 = new Thread(threadYield, "线程2");
thread1.start();
thread2.start();
}
}

线程联合: join方法
join方法允许一个线程等待另一线程的完成。如果t是Thread正在执行其线程的对象,t.join();导致当前线程暂停执行,直到t的线程终止。重载join允许程序员指定等待时间。但是,与一样sleep, join依赖于OS进行计时,因此不应该假定join它将完全按照您指定的时间等待。

public class ThreadJoin implements Runnable {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("子线程" + i);
}
}
public static void main(String[] args) {
ThreadJoin threadJoin = new ThreadJoin();
Thread thread = new Thread(threadJoin);
thread.start();
for (int i = 0; i < 100; i++) {
System.out.println("主线程main" + i);
if(i == 90) {
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}

线程停止
在 Java 中有以下 3 种方法可以终止正在运行的线程:

  1. 使用退出标识,使得线程正常退出,即当run方法完成后进程终止。
public class ThreadStop implements Runnable {
private boolean flag = true;
@Override
public void run() {
int i = 0;
while (flag) {
System.out.println("子线程" + i++);
}
}
public void stop() {
this.flag = false;
}
  1. 使用stop强行中断线程(此方法为作废过期方法),不推荐使用。
public static void main(String[] args) {
ThreadStop threadStop = new ThreadStop();
Thread thread = new Thread(threadStop);
thread.start();
for (int i = 0; i < 100; i++) {
System.out.println("主线程main" + i);
if (i == 90) {
threadStop.stop();
System.out.println("子线程停止了");
}
}
}
}
  1. 使用interrupt方法中断线程, 不推荐使用。

守护线程
Java线程分为两种: 用户线程和守护线程。
用户线程可以认为是系统的工作线程,它会完成这个程序要完成的业务员操作。
守护线程是一种特殊的线程,就和它的名字一样,它是系统的守护者,在后台默默完成一些系统性的服务,比如垃圾回收线
程。
如果用户线程全部结束,则意味着这个程序无事可做。守护线程要守护的对象已经不存在了,那么整个应用程序就结束了。

~~public class ThreadDaemon {
public static void main(String[] args) {
Daemon daemon = new Daemon();
Thread thread1 = new Thread(daemon);
thread1.setDaemon(true);
thread1.start();
Me me = new Me();
Thread thread2 = new Thread(me);
thread2.start();
}
}
class Me implements Runnable {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("我的努力奔跑" + i);
}
}
}
class Daemon implements Runnable {
@Override
public void run() {
int i = 0;
while (true) {
System.out.println("我的守护你" + i++);
}
}
}

线程同步

线程冲突
当在不同线程中运行作用于相同数据的两个操作时,就会发生干扰。
这意味着这两个操作由多个步骤组成,并且步骤顺序重叠。

  1. 检索的当前值c。
  2. 将检索到的值增加1。
  3. 将增加的值存储回c。

同步语句
Java编程语言提供了两种基本的同步习惯用法: 同步语句(synchronized statements )和同步方法(synchronized methods )。
创建同步代码的一种方法是使用同步语句。与同步方法不同,同步语
句必须指定提供内部锁的对象。
同步语句对于通过细粒度同步提高并发性很有用。

public class SynchronizedStatements implements Runnable {
public static int ticket = 100;
@Override
public void run() {
while (ticket > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized ("") {
if (ticket <= 0) {
return;
}
System.out.println(Thread.currentThread().getName()
+ "卖了1张票,剩余" + --ticket + "张票");
}
}
}
public static void main(String[] args) {
SynchronizedStatements synchronizedStatements
= new SynchronizedStatements();
Thread thread1 = new Thread(synchronizedStatements, "售票员1");
thread1.start();
Thread thread2 = new Thread(synchronizedStatements, "售票员2");
thread2.start();
Thread thread3 = new Thread(synchronizedStatements, "售票员3");
thread3.start();
}
}

同步方法
要使同步方法,只需将synchronized关键字添加到其声明中。
同步方法提供了一种防止线程干扰和内存一致性错误的简单策略:如果一个对象对一个以上线程可见,则对该对象变量的所有读取或写入均通过synchronized方法完成。

public class SynchronizedMethods implements Runnable {
public static int ticket = 100;
@Override
public void run() {
sellTicket();
}
public synchronized void sellTicket() {
while (ticket > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()
+ "卖了1张票,剩余" + --ticket + "张票");
}
}
public static void main(String[] args) {
SynchronizedMethods synchronizedMethods
= new SynchronizedMethods();
Thread thread1 = new Thread(synchronizedMethods, "售票员1");
thread1.start();
Thread thread2 = new Thread(synchronizedMethods, "售票员2");
thread2.start();
Thread thread3 = new Thread(synchronizedMethods, "售票员3");
thread3.start();
}
}

线程死锁

死锁是一种特定的程序状态,在实体之间,由于循环依赖导致彼此一直处于等待之中,没有任何个体可以继续前进。
死锁不仅仅在线程之间会发生,存在资源独占的进程之间同样也可能出现死锁。通常来说,我们大多是聚焦在多线程场景中的死锁,指两个或多个线程之间,由于互相持有对方需要的锁,互相等待,而永久处于阻塞状态。

public class ThreadDeadLock {
public static void main(String[] args) {
DeadLockA deadLockA = new DeadLockA();
Thread threadA = new Thread(deadLockA, "线程1");
DeadLockB deadLockB = new DeadLockB();
Thread threadB = new Thread(deadLockB, "线程2");
threadA.start();
threadB.start();
}
}
class DeadLockA implements Runnable {
@Override
public void run() {
synchronized ("A") {
System.out.println(Thread.currentThread().getName()
+ "持有了A锁,等待B锁。。。 ");
synchronized ("B") {
System.out.println(Thread.currentThread().getName()
+ "持有了A锁和B锁");
}
}
}
}
class DeadLockB implements Runnable {
@Override
public void run() {
synchronized ("B") {
System.out.println(Thread.currentThread().getName()
+ "持有了B锁,等待A锁。。。 ");
synchronized ("A") {
System.out.println(Thread.currentThread().getName()
+ "持有了B锁和A锁");
}
}
}
}

线程协调

waitnotify方法
死锁发生时的条件:
( 1)互斥条件:一个资源每次只能被一个进程使用。
( 2)请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
( 3)不剥夺条件: 进程已获得的资源,在未使用完之前,不能强行剥夺。
( 4)循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

public class ThreadCoordinate {
public static void main(String[] args) {
CoordinateA coordinateA = new CoordinateA();
Thread threadA = new Thread(coordinateA, "线程1");
CoordinateB coordinateB = new CoordinateB();
Thread threadB = new Thread(coordinateB, "线程2");
threadA.start();
threadB.start();
}
}
class CoordinateA implements Runnable {
@Override
public void run() {
synchronized ("A") {
System.out.println(Thread.currentThread().getName()
+ "持有了A锁,等待B锁。。。 ");
try {
"A".wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized ("B") {
System.out.println(Thread.currentThread().getName()
+ "持有了A锁和B锁");
}
}
}
}
class CoordinateB implements Runnable {
@Override
public void run() {
synchronized ("B") {
System.out.println(Thread.currentThread().getName()
+ "持有了B锁,等待A锁。。。 ");
synchronized ("A") {
System.out.println(Thread.currentThread().getName()
+ "持有了B锁和A锁");
"A".notify();
}
}
}
}

懒汉式单例模式
在使用这个对象时,才去查看这个对象是否创建。 如果没创建就马上创建; 如果已经创建,就返回这个实例。线程不安全,需要加上同步锁,影响了程序执行效率。

public class ThreadSingleton {
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
HelloRunnable helloRunnable = new HelloRunnable();
Thread thread = new Thread(helloRunnable);
thread.start();
}
}
}
class Lazybones {
public Lazybones() {
System.out.println("对象实例化了");
}
private static Lazybones lazybones = null;
public static Lazybones getLazybones() {
synchronized ("") {
if (lazybones == null) {
lazybones = new Lazybones();
}
}
return lazybones;
}
}
class HelloRunnable implements Runnable {
@Override
public void run() {
Lazybones.getLazybones();
}
}

生产者消费者例子



public class Demo4 {
    public static void main(String[] args) {
        SynContainer container = new SynContainer();
        new Productor(container).start();
        new Consumer(container).start();


    }
}

class Productor extends Thread {
    SynContainer  container;
    public Productor(SynContainer container){
        this.container=container;
    }
    @Override
    public void run() {
        for (int i = 1; i <= 100; i++) {
            container.push(new Chicken(i));
            System.out.println("生产了"+i+"只鸡");

        }
    }

}
class Consumer  extends Thread{
    SynContainer  container;
    public Consumer (SynContainer container){
        this.container=container;
    }
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("消费了-->"+container.pop().id+"只鸡");
        }
    }
}
class Chicken{
    int id;

    public Chicken(int id) {
        this.id = id;
    }
}
class SynContainer{
    int count=0;
    Chicken[] chickens= new Chicken[10];
   public synchronized  void  push(Chicken chicken){

       if (count==chickens.length){
           try {
               this.wait();
           } catch (InterruptedException e) {
               e.printStackTrace();
           }
       }
           chickens[count]=chicken;
           count++;
           this.notifyAll();
       }




   public synchronized Chicken pop(){
       if(count==0){
           try {
               this.wait();
           } catch (InterruptedException e) {
               e.printStackTrace();
           }
       }
       count--;
          Chicken chicken= chickens[count];

          this.notifyAll();
          return chicken;

   }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值