Java35:多线程

进程是操作系统中运行的一个任务

线程归属与一个进程


一个进程至少一个线程

所有线程共享进程的内存


线程通常用于一个程序中需要同时完成多个任务的情况,我们可以将每个人物定义为一个线程,使他们可以一同工作

1:事情要同时干,例如:

2:使用多线程可以提高效率,例如:下载


并发原理:

    多个线程“同时”运行只是我们感官的一种表现

    实际上线程是并发运行的

线程  调度分配CPU的时间片给不通的线程得到时间片的线程被cpu运行,其他线程等待,线程调度会尽可能均匀的分配时间片给不同的线程


有向后顺序的运行方式是同步运行

在一个线程中


各自干各自的叫做异步

在多个线程





线程优先级


    线程的切换时由线程调用控制 无法通过代码来干涉,但是通过提高线程的优先级来最大程度的改善线程获取的时间片的几率

理论上的值,但不是绝对的

线程的优先级 10级 1-10 1最低 10 最高 5是默认(有3个常量 )

void setPriority(int priority) 设置线程的优先级



守护线程(后台线程)

    与普通的编程表现上没有什么区别,通过 void setDarmon(boolean)

    true  守护线程

    守护线程的特点是 当进程中只剩下守护线程时 所有守护线程强制终止

    GC 就是一个后台进程


sleep方法

    线程阻塞

yield 方法

    Thread 的静态方法

        static void yield()

        该方法用于使当前线程主动让出当次CPU时间片回到Runna状态,等待分配时间片

join方法

    void join()

    该方法用于等待当前线程结束

        等另外一个线程结束,在运行

    该方法声明抛出InterrruptException



解决多线程并发的安全的问题的办法是 将异步变为同步

    产生多线程并发安全的原因是 多线程并发操作同一数据

    synchronized关键字

        多个线程并发读写同一个临界资源时会发生“线程并发安全问题”

            常见的临界资源 :

                多线程共享实例变量

                多线程共享静态公共变量

            解决问题的方法:

                将异步操作变为同步操作

                异步 多线程并发的操作,相当于各干各的

                同步 有先后顺序的操作,你先干完我再上

        同步代码块

                多个线程看到的要是同一个对象(是谁不重要)

        synchronized(同步监视器-锁对象引用){

            //代码块   

        }

        方法中所有的代码都需要同步也可以直接在方法上加锁

        每个java对象都可以用做一个实现同步的锁,线程进入同步代码块之前会自动获得锁,并且在退出同步代码块时自动释放锁,而且无论是通过正常途径退出还是通过抛异常退出都一样,获得内置锁的唯一途径就是进入由这个锁保护的同步代码块货方法

    


        同步代码块在某一个非静态方法中,通常锁对象写this

                在静态方法中,就不能写this   在最外面定义一个对象给他看



wait 和 notify


多线程之间需要协调工作

在Object 上定义的 不是Thread 上定义的 


    notify 只会随机解除一个在当前对象上等待的线程

        这也是他不足的地方

 调用那个对象的wait或者notify 就应当对当前对象加锁,锁对象就是当前对象

多个线程在一个线程等

obj.notifyAll()


线程安全,API 非线程安全API


StringBuffer 是同步的

StringBuilder  不是同步的


Vectir 和 Hashtable 是同步的

ArrayList 和HashMap 不是同步的



使用Collections 集合的工具类 

Collections.synchronizedList()

List

Collections.synchronizedMap()

Map

Collections.synchronizedSet()

Set 


List<String> list = new ArrayList<String>();

list.add("1");

list.add("2");

list.add("3");

list.add("4");

list.add("5");

list = Collections.synchronizedList(list);

线程安全的了




线程池

    ExecutorService 用于管理线程池的类

        有两个作用

            控制线程数量

            重用线程

    当一个程序中入创建大量线程,并在任务结束后销毁,会给系统带来过度消耗资源,以及过度切换的危险,可能导致系统崩溃, 使用线程池来解决这个问题


Executors.newCachedThreadPool()

创建一个可根据需要创建新线程的线程池但是在以前构造的线程可用时将重用他们


Executors.newFixedThreadPool(int nThreads)

创建一个可重用戈丁线程集合的线程池以共享的***队列方式来运行这些线程

nThreads = 20   那就20个线程  多余在等待


Exceutors.newScheduledThreadPool(int corePoolSize)

创建一个线程池 它可安排在给定延迟后运行命令或者定期执行


Exceutors.newSingleThreadExecuor()

创建一个使用单个worker线程的Executor 以***队列方式来运行该线程



双缓冲队列

BlockingQueue

有以下:

    ArrayBlockingQueue

        规定大小的BlockingDeque  构造函数必须带一个int参数来指定大小所含的对象是FIFO顺序排序

    LinkedBlockingQueue

        大小不定的BlockingDeque 若构造函数带一个规定大小的参数 生成BlockingDeque有大小限制若不带大小参数所生成的BlockingDeque的大小由Integer.MAX_VALUE来决定 所含的对象是以FIFO排序

    PriorityBlockingQueue

        类似于LinkedBlockDeque 但是所含对象的排序不是FIFO而是依据对象的自然排序顺序或者是构造函数的Comparator来决定的  第一个取出来的是最小的

    SynchronousQueue

        特殊的BlockingQueue 对他的操作必须是放和取交替完成的  也就是只有一个元素






创建一个线程的步骤


1、定义一个类  并继承Thread类

        》》Thread 类是线程类,其中定义操作线程的相关方法

2、重写 run方法 该方法中应该定义的内容就是要并发运行的代码片段

3、实例化线程并启动


class MyThread extends Thread{
    public void run(){
        while(true){
            System.out.prinitln("my");
        }
    }
}
class YourThread extends Thread{
    public void run(){
        while(true){
            System.out.println("your");
        }
    }
}
public class Test{
    public static void main(String[] args{
        Thread my = new MyThread();
        Thread your = new YourThread();
        my.start();
        your.start();
    }
}


第二种


任务就是任务 线程就是线程 线程只关心可以并发就好了  给什么任务就并发运行就好了

定义一个类 实现 Runnable这个接口  这个就是任务

重写run方法

实例化 类 也就是任务

实例化一个Thread  也就是线程

把任务交给线程并启动

class MyRunnable implements Runnable{
    public void run(){
        while(true){
            System.out.println("MY");
        }
    }
}
class YourRunnable implements Runnable{
    public void run(){
        while(true){
            System.out.println("YOUR")
        }
    }
}
public class Test{
    public static void main(String[] args){
        Runnable r1 = new MyRunnable();
        Runnable r2 = new YourRunnable();
        Thread t1 = new Thread(r1);
        Thread t2 = new  Thread(r2);
        t1.start();
        t2.start();
    }
}


第三种

使用匿名类

public class Main3 {
	public static void main(String[] args) {
		Thread t1 = new Thread() {
			public void run() {
				while (true) {
					System.out.println("my");
				}
			}
		};
		Thread t2 = new Thread() {
			public void run() {
				while (true) {
					System.out.println("your");
				}
			}
		};

		t1.start();
		t2.start();
	}
}
public class Main4 {
	public static void main(String[] args){
		Thread t1 =new Thread(new Runnable() {
			
			@Override
			public void run() {
				while(true){
					System.out.println("my");
				}
			}
		});
		
		Thread t2 =new Thread(new Runnable() {
			
			@Override
			public void run() {
				while(true){
					System.out.println("your");
				}
			}
		}); 
		t1.start();
		t2.start();
		
	}
}



线程常用的方法

static void sleep(long time)

异常  外界可能会中断  比如线程在阻塞状态 调用了interrupt

void interrupt()

中断线程



Thread.currentThread()

Thread 的静态方法  可以用于获取运行当前代码片段的线程是谁

getId() 返回线程的标识符

String getName() 返回该线程的名称

getPriority()返回线程的优先级

getState() 返回线程的状态

isAlive() 线程是否是活动状态

isDaemon()线程是否为守护线程

isInterrupted()线程是否已经中断


setPriority() 设置线程的优先级


setDaemon() 设定为守护线程 



join使线程同步

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值