Java Threads 创建线程

Process and threads

Process

  • A process runs isolated from other processes
  • A process cannot directly access shared data in other processes
  • The resources of the process, e.g. memory and CPU time, are allocated to it via the operating system
  • Example: Java Virtual Machine is a process

Thread

  • A thread is a lightwight process
    • Each has its own stack
    • Can access shared data of other threads in the same process
    • Every thread has its own memory cache
    • If a thread reads shared data, it stores this data in its own memory cache.A thread can re-read the shared data

Key Concepts in concurrent programming

Atomicity

  • Cannot be interrupted
  • Once it starts is always completes
  • One example assignment a=5

Visibility

什么是线程间的可见性?
一个线程对共享变量值的修改,能够及时的被其他线程看到。
线程间的可见性

Order of execution

The order in concurrent programming is not guaranteed!

Critical code

A part of code that must be executed by a single thread at one time

Two ways of creating a thread

Creating a thread by implements


public class MyFirstRunnable implements Runnable
{
    public void run(){//implement the abstract run() method of the runnable interface
        System.out.println("Thread");
    }
}

MyFirstRunnable xyz = new MyFirstRunnable();
Thread thread = new Thread(xyz);
thread.start();

You can use the same runnable several times

Runnable runnable = new MyFirstRunnable();

for(int i =0;i<25;i++>){
    new Thread(runnable).start();
}

//How many threads will be running?
//26 together with the main thread

Creating a thread using extends

public class MyThread extends Thread{
    public void run(){//override the run() method
        System.out.println("MyThread running");
        System.out.println("do some interesting stuff");
		System.out.println("Leaving thread using MyThread extends Thread");
    }

    public static void main(String[] args) {
		// This approach uses a class the extends Thread
		MyFirstThreadExtend myFirstThreadExtend = new MyFirstThreadExtend();
		myFirstThreadExtend.start();
	}
}

Give names to a Thread

public class Order implements Runnable {
    public void run() {
    String threadName = Thread.currentThread().getName();
    System.out.println("I'm running in thread‐" + threadName);
    }

    public static void main(String[] args) {
    Order order = new Order();
        for (int i = 0; i < 25; i++) {
        Thread thread = new Thread(order);
        thread.setName("Thread " + i);
        thread.start();
        }
    }
}

One of the results:

I'm running in thread-Thread 0
I'm running in thread-Thread 2
I'm running in thread-Thread 4
I'm running in thread-Thread 3
I'm running in thread-Thread 6
I'm running in thread-Thread 1
I'm running in thread-Thread 7
I'm running in thread-Thread 9
I'm running in thread-Thread 10
I'm running in thread-Thread 11
I'm running in thread-Thread 5
I'm running in thread-Thread 12
I'm running in thread-Thread 16
I'm running in thread-Thread 18
I'm running in thread-Thread 14
I'm running in thread-Thread 15
I'm running in thread-Thread 19
I'm running in thread-Thread 8
I'm running in thread-Thread 13
I'm running in thread-Thread 17
I'm running in thread-Thread 22
I'm running in thread-Thread 24
I'm running in thread-Thread 21
I'm running in thread-Thread 20
I'm running in thread-Thread 23

当java虚拟机(也就是经常说的 JVM)执行main方法的时候,他会找操作系统(也就是 os)开辟一条main方法通向cpu的路径,这个路径就是main线程,也就是所说的主线程。

接着cpu通过这个线程,也就是这个路径,就可以执行main方法了。

当我们new了一个thread对象,这个时候又开辟了一条通向cpu的路径,而这条路径是用来执行run方法的。

而现在对于cpu而言,他就有了两条执行的路径,cpu就有了选择的权利,cpu他喜欢谁,就会执行哪条路径,我们是控制不了cpu的,所有就有了出现随机打印的结果。

反过来说,两个线程,一个main线程,一个新线程,他们一起抢夺cpu的执行权(即 cpu的执行时间),谁抢到了,谁先执行。

Inline definition

inline:

Thread t = new Thread(new Runnable()
{ public void run() { /*stuff here*/ } });
t.start();

Difference between mythread.run() and mythread.start()

Java中Thread.start和Thread.run

start() : 它的作用是启动一个新线程,新线程会执行相应的run()方法。start()不能被重复调用。
run() : run()就和普通的成员方法一样,可以被重复调用。单独调用run()的话,会在当前线程中执行run(),而并不会启动新线程。

// Demo.java 的源码
class MyThread extends Thread{
    public MyThread(String name) {
        super(name);
    }

    public void run(){
        System.out.println(Thread.currentThread().getName()+" is running");
    }
};

public class Demo {
    public static void main(String[] args) {
        Thread mythread=new MyThread("mythread");

        System.out.println(Thread.currentThread().getName()+" call mythread.run()");
        mythread.run();

        System.out.println(Thread.currentThread().getName()+" call mythread.start()");
        mythread.start();
    }
}

运行结果:

main call mythread.run()
main is running
main call mythread.start()
mythread is running

结果说明:
(01) Thread.currentThread().getName()是用于获取“当前线程”的名字。当前线程是指正在cpu中调度执行的线程。
(02) mythread.run()是在“主线程main”中调用的,该run()方法直接运行在“主线程main”上。
(03) mythread.start()会启动“线程mythread”,“线程mythread”启动之后,会调用run()方法;此时的run()方法是运行在“线程mythread”上。

sleep method

  • Only make current thread sleep
  • Sleep for a certain milliseconds
  • Syntax: Thread.sleep(996)
  • The thread will pause(suspend)
  • Free up CPU time for other threads
public void run(){
    try{
    Thread.sleep(1000);
    }
    catch(InterruptedException e){
    e.printStackTrace();
    }
}

InterruptedException

  • This exception is thrown when a thread is interrupted
  • Enables you to deal with the interrupt elegantly
  • Another thread might needs resources

How to interrupt a thread

thread.interrupt sets the interrupted flag
Blocking methods, such Thread.sleep(), try to detect when a thread has been interruptd and return early
They respond to interruption by clearing the setting the flag to false and throwing InterruptedException.
Interrupting a thread that is not live need not have any effect.

  • If any thread is in sleeping or waiting state (i.e. sleep() or wait() is
    invoked), calling the interrupt() method on the thread, breaks out the
    sleeping or waiting state throwing InterruptedException.
  • If the thread is not in the sleeping or waiting state, calling the
    interrupt() method performs normal behaviour and doesn’t interrupt
    the thread but sets the interrupt flag to true.
    当一个线程处于等待,睡眠,或者占用,也就是说阻塞状态,而这时线程被中断就会抛出这类错误。Java6之后结束某个线程A的方法是A.interrupt()。如果这个线程正处于非阻塞状态,比如说线程正在执行某些代码的时候,被interrupt,那么该线程的interrupt变量会被置为true,告诉别人说这个线程被中断了,这时不会有interruptedException。但如果这时线程被阻塞了,比如说正在睡眠,那么就会抛出这个错误。请注意,这个时候变量interrupt置为false。在写代码的时候最好考虑一下这个标志位。
public void interrupt()
public static boolean interrupted()
public boolean isInterrupted()

Yield

  • The executing thread is suspended
  • The CPU is given to some other runnable thread
  • This thread will wait until the CPU becomes available again
    Technically, in process scheduler’s terminology,
    • the executing thread is returned to the ready queue of the processor and
    • waits for its next turn.
      yield方法
      Java线程中的Thread.yield( )方法,译为线程让步。顾名思义,就是说当一个线程使用了这个方法之后,它就会把自己CPU执行的时间让掉,

让自己或者其它的线程运行,注意是让自己或者其他线程运行,并不是单纯的让给其他线程。

yield()的作用是让步。它能让当前线程由“运行状态”进入到“就绪状态”,从而让其它具有相同优先级的等待线程获取执行权;但是,并不能保

证在当前线程调用yield()之后,其它具有相同优先级的线程就一定能获得执行权;也有可能是当前线程又进入到“运行状态”继续运行!

举个例子:一帮朋友在排队上公交车,轮到Yield的时候,他突然说:我不想先上去了,咱们大家来竞赛上公交车。然后所有人就一块冲向公交车,

有可能是其他人先上车了,也有可能是Yield先上车了。

但是线程是有优先级的,优先级越高的人,就一定能第一个上车吗?这是不一定的,优先级高的人仅仅只是第一个上车的概率大了一点而已,

最终第一个上车的,也有可能是优先级最低的人。并且所谓的优先级执行,是在大量执行次数中才能体现出来的。

Interrupt

How to get a reference to yourself as a thread…

public class MyThread implements Runnable{
    public void run(){
        Thread.currentThread().interrupt();
        //If implements Runnable eed to use 
        //Thread.currentThread()
    }
}

wait(), notify(), notifyAll()

sleep()和wait()的区别
sleep和wait的区别,wait需要抛出异常吗?

  1. sleep(long millis)是Thread的静态方法,用于为线程指定睡眠时间,期间并不释放同步锁,时间到达后恢复线程执行;wait()是Object的final方法,会把调用者线程挂起,同时释放锁,直到被notify/notifyAll等方法唤醒或者超时,之后和其它线程共同竞争CPU。

  2. 最主要是sleep()不释放同步锁,而wait()释放同步锁,使得其他线程可以使用同步控制块或者方法。

  3. wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用。
    Methods wait, notify and notifyAll may only be called when the current thread has a lock on the object (i.e., from within a synchronized method or from within a method that has been called by a synchronized method).

  4. sleep,wait必须捕获异常,而notify和notifyAll不需要捕获异常。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wwwTVMck-1601130275367)(https://s1.ax1x.com/2020/09/22/wOWj3D.png)]

Since there is no way of specifying which thread is to be woken, this is only really appropriate if there is only one waiting thread.
If all threads waiting for a lock on a given object are to be woken, then we use notifyAll.
This wait() method should only be called by a thread that is the owner of this
object’s monitor.

public final void wait()
• Exception
• IllegalMonitorStateException − if the current thread is not the owner
of the object’s monitor.
• InterruptedException − if another thread has interrupted the current
thread. The interrupted status of the current thread is cleared when
this exception is thrown.

Homework for lesson1

  1. Write a Java Thread using both methods that:
    Loops 100 times printing “Hello World”
   public class HelloWorld implements Runnable{
	public void run() {
		System.out.println("hello");
	}
	
	public static void main(String[] args) {
		HelloWorld helloWorld = new HelloWorld();
		for(int i =0;i<100;i++) {
		Thread mythread = new Thread(helloWorld);
		mythread.start();
		}
	}
}
public class HelloWorld extends Thread{
	public void run() {
		int i=0;
		while(i<100) {
			//print hello
			System.out.println("hello");	
			//counter++
			i++;	
		}	
	}
	
	public static void main(String[] args) throws InterruptedException {
		
		//prepare the thread
		HelloWorld helloWorld = new HelloWorld();
		
		//Start the thread
		helloWorld.start();
		
	}
	
}
  1. Make the thread sleep for 1 second between each iteration
public class HelloWorld implements Runnable{
	public void run() {
		int i=0;
		while(i<100) {
			
			//sleep 1s
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			
			//print hello
			System.out.println("hello");
			
			//counter++
			i++;	
		}	
	}
	
	public static void main(String[] args) throws InterruptedException {
		
		//prepare the thread
		HelloWorld helloWorld = new HelloWorld();
		Thread mythread = new Thread(helloWorld);
		
		//Start the thread
		mythread.start();
		
	}
	
}
  1. Write code to interrupt the thread so that it finishes early
public class HelloWorld implements Runnable{
	public void run() {
		while(true) {	
			System.out.println("hello");	
			if(Thread.currentThread().isInterrupted()==true) {
				System.out.println("Terminated!");
				break;
			}
			
		}	
	}
	
	public static void main(String[] args) throws InterruptedException {
		
		//prepare the thread
		HelloWorld helloWorld = new HelloWorld();
		Thread mythread = new Thread(helloWorld);
		
		//Start the thread
		mythread.start();
		
		//Run some rubbish code
		for(int i=0;i<1000000;i++) {
		int ii=1000;
		}
		
		//Interrupt
		mythread.interrupt();
		
	}
	
}
posted @ 2020-09-26 22:27  無数  阅读(5)  评论(0编辑  收藏  举报