java thread study

网友投稿 601 2022-05-30

0. 用runnable创建线程具有面向对象的思想。

1. quartz  定时器开源库。

3.  多线程间的互斥:

(1)多线程间的互斥,用synchronized关键字,两个线程用互斥锁必须用同一个对象才能实现互斥。

(2) 两个非静态函数前加synchronized关键字,它们的公用锁是this,就是当前对象实例。

(3)静态函数前加synchronized关键字,它用的锁对象是.class字节码,这个时u候与要将非静态函数的synchronized(this)锁改为synchronized(MyClass.class),即字节码锁

两个函数这才使用了同一个锁:类的字节码对象,从而才实现了互斥。

例如:2 个线程调用同一个Output对象的output1(“gaoxiaowei”)和output2(“lichao”)两个函数, 会出现打印gaoxiaowei  lichao    gaolichao xiaowei这样第二行错乱的问题。

在这里临界资源是输出屏幕? 我如果让一个线程调用ouput1对象的output,然后另一个线程调用output2对象的output,在不加锁的情况下会错乱吗?

答:

(1)如果output函数的同步锁是object.class字节码时,就不会错乱,因为两个线程 的两个output对象在执行output1函数时,用的是同一把锁object.class;

(2)如果output的同步锁是this,那么会错乱,因为两个线程分别持有2个对象output1与ouput2,是两个this,因此output函数上的synchronized用的o是2把不同的

this锁,各自执行各自的,都可以在这个临界资源——屏幕上输出。如第一个线程正在输出gaolichao结果第二个线程打印lichao插到了第一个线程的输出中间。

(3)是的,这里的临界资源就是显示器,而不是公用的output类对象,因为即使2个线程分别创建一个output对象:output1与output2,如果锁不是同一个的话,

也会出现打印错误。除非有2个显示器,一个线程往显示器1输出,另一个线程往显示器2输出,这才不冲突,因为2个已经是1对1,不存在公用竞争问题。

4.多线程间的同步

wait 和 notify

现在有这么一个题目:子线程执行10次,然后主线程再执行100次,接着轮到子线程再执行10次,然后主线程又执行100次,两个线程这样轮流执行,总共50回。

step1: 定义一个业务类,封装两个函数:(1)打印10次sub  (2)打印100次main;

step2: 定义1个子线程,外层for循环都是50次,然后每循环1次调用业务类中的 函数(1u)打印10次sub

主线程,外层for循环都是50次,然后每循环1次调用业务类中的 函数(2)打印50次main

step3:先解决互斥问题:就是在打印sub的10次循环时,不能穿插打印main;同理打印main的100次的时候,不能穿插子线程的sub打印。这个好办,给业务类的

函数1和函数2前加synchronized关键字,这样就实现了打印sub的10次时,由于正在占用同一个对象锁this,因此它不会被函数(2)打断。

step4:解决同步配合问题,先子线程打印10次,子线程打印完了,然后执行notify,唤醒主线程去打印100次(主线程刚开始会调用waite),然后主线程打印完100次,再去唤醒子线程去打印。

注意synchronized括起来的对象要与调用wait,notify是同一个对象,并且这个object.notify,object.wait中的object要被括在synchronized里,否则会报错:Java.lang.IllegalMonitorStateException

实例代码如下:

import java.util.concurrent.atomic.AtomicInteger;

public class TraditionalThreadCommunication {

/**

* @param args

*/

public static void main(String[] args) {

final Business business = new Business();

new Thread(

new Runnable() {

@Override

public void run() {

for(int i=1;i<=50;i++){

business.sub(i);

}

}

}

).start();

for(int i=1;i<=50;i++){

business.main(i);

}

}

}

class Business {

private boolean bShouldSub = true;

Object obj;

public Business()

{

obj = new Object();

}

public synchronized void sub(int i){

synchronized(obj)

{

while(!bShouldSub){

try {

obj.wait();

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

for(int j=1;j<=10;j++){

java thread study

System.out.println("sub thread sequence of " + j + ",loop of " + i);

}

bShouldSub = false;

obj.notify();

}

}

public  void main(int i){

synchronized(obj)

{

while(bShouldSub){

try {

obj.wait();

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

for(int j=1;j<=100;j++){

System.out.println("main thread sequence of " + j + ",loop of " + i);

}

bShouldSub = true;

obj.notify();

}

}

}

或者:

public class TraditionalThreadCommunication {

public static void main(String[] args) {

final Business business = new Business();

new Thread(

new Runnable() {

@Override

public void run() {

for(int i=1;i<=50;i++){

business.sub(i);

}

}

}

).start();

for(int i=1;i<=50;i++){

business.main(i);

}

}

}

class Business {

private boolean bShouldSub = true;

public synchronized void sub(int i){

while(!bShouldSub){

try {

this.wait();

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

for(int j=1;j<=10;j++){

System.out.println("sub thread sequence of " + j + ",loop of " + i);

}

bShouldSub = false;

this.notify();

}

public synchronized void main(int i){

while(bShouldSub){

try {

this.wait();

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

for(int j=1;j<=100;j++){

System.out.println("main thread sequence of " + j + ",loop of " + i);

}

bShouldSub = true;

this.notify();

}

}

5. 多线程间的互斥,用synchronized关键字包裹的函数内部如果生成了 一个死循环线程,那么这个函数的锁子能释放吗?

答:能。因为synchronized是用于当前线程同步的;还有就是生成的那个线程并不会阻塞当前函数的执行,函数执行完成后自然会释放synchronized锁。

6.当一个线程处于sleep时,Thread.isAlive函数返回false

7.线程范围内的共享变量

同一个变量,在线程间共享,例如下面的变量x,线程内独立,表示线程内是一份独立的数据。

(1)可以用hashmap.put(Thread.name, data);  来实现

(2)ThreadLocal来实现

下面的x,是演示单个共享变量

package cn.itcast.heima2;

import java.util.HashMap;

import java.util.Map;

import java.util.Random;

public class ThreadLocalTest {

private static ThreadLocal x = new ThreadLocal();

private static ThreadLocal myThreadScopeData = new ThreadLocal();

public static void main(String[] args) {

for(int i=0;i<2;i++){

new Thread(new Runnable(){

@Override

public void run() {

int data = new Random().nextInt();

System.out.println(Thread.currentThread().getName()

+ " has put data :" + data);

x.set(data);

/*                    MyThreadScopeData myData = new MyThreadScopeData();

myData.setName("name" + data);

myData.setAge(data);

myThreadScopeData.set(myData);*/

MyThreadScopeData.getThreadInstance().setName("name" + data);

MyThreadScopeData.getThreadInstance().setAge(data);

new A().get();

new B().get();

}

}).start();

}

}

static class A{

public void get(){

int data = x.get();

System.out.println("A from " + Thread.currentThread().getName()

+ " get data :" + data);

/*            MyThreadScopeData myData = myThreadScopeData.get();;

System.out.println("A from " + Thread.currentThread().getName()

+ " getMyData: " + myData.getName() + "," +

myData.getAge());*/

MyThreadScopeData myData = MyThreadScopeData.getThreadInstance();

System.out.println("A from " + Thread.currentThread().getName()

+ " getMyData: " + myData.getName() + "," +

myData.getAge());

}

}

static class B{

public void get(){

int data = x.get();

System.out.println("B from " + Thread.currentThread().getName()

+ " get data :" + data);

MyThreadScopeData myData = MyThreadScopeData.getThreadInstance();

System.out.println("B from " + Thread.currentThread().getName()

+ " getMyData: " + myData.getName() + "," +

myData.getAge());

}

}

}

class MyThreadScopeData{

private MyThreadScopeData(){}

public static /*synchronized*/ MyThreadScopeData getThreadInstance(){

MyThreadScopeData instance = map.get();

if(instance == null){

instance = new MyThreadScopeData();

map.set(instance);

}

return instance;

}

//private static MyThreadScopeData instance = null;//new MyThreadScopeData();

private static ThreadLocal map = new ThreadLocal();

private String name;

private int age;

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

}

8.多个线程间共享数据的探讨

方法1:new Thread(new Runnable()

{

data1.decrement();

}

)

方法2:        new Thread(new MyRunnable1(data2)).start();

new Thread(new MyRunnable2(data2)).start();

将数据data2作为构造函数参数传到Runnable里去。

方法3:

定义2个Runnable内部类,访问外部类的成员变量j

方法1和方法2的代码:

package cn.itcast.heima2;

public class MultiThreadShareData {

private static ShareData1 data1 = new ShareData1();

public static void main(String[] args) {

ShareData1 data2 = new ShareData1();

new Thread(new MyRunnable1(data2)).start();

new Thread(new MyRunnable2(data2)).start();

final ShareData1 data1 = new ShareData1();

new Thread(new Runnable(){

@Override

public void run() {

data1.decrement();

}

}).start();

new Thread(new Runnable(){

@Override

public void run() {

data1.increment();

}

}).start();

}

}

class MyRunnable1 implements Runnable{

private ShareData1 data1;

public MyRunnable1(ShareData1 data1){

this.data1 = data1;

}

public void run() {

data1.decrement();

}

}

class MyRunnable2 implements Runnable{

private ShareData1 data1;

public MyRunnable2(ShareData1 data1){

this.data1 = data1;

}

public void run() {

data1.increment();

}

}

class ShareData1 /*implements Runnable*/{

/*        private int count = 100;

@Override

public void run() {

// TODO Auto-generated method stub

while(true){

count--;

}

}*/

private int j = 0;

public synchronized void increment(){

j++;

}

public synchronized void decrement(){

j--;

}

}

方法3的代码:

外部类:

private int j = 0;

public synchronized void increment(){

j++;

}

public synchronized void decrement(){

j--;

}

内部类:

MyIncrementRunnable()

{

increment();  //内部类调用外部类成员,还是以外部类对象为同步锁

}

MyDecrementRunnable()

{

decrement();

}

Java 任务调度

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:小花带你一周hold住人人学IOT(五) 操作系统,轻量开源
下一篇:一名全栈工程师的必备工具箱
相关文章