JavaでThreadとかsemaphoreとかやってみた

　マルチタスク、スレッドやセマフォって何なのかなと思い、Javaで色々遊んでみました。しかし、コンソールに吐き出されるものだけでは今一納得できなくて、ビジュアルにしてみました。良いのか役に立たないものか自分でもわからないので投稿してみます。Eclipse IDE(pleiades 2022-12)で検証しました。
![マルチタスク.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3189926/108e682d-4f58-698e-1d9d-adc4e9232d6e.jpeg)
　あまり説明のしようもないのですが、スレッドは最大2個で全部で6個のタスクを行ったら終了です。スレッドを立ち上げる際に生存時間をランダムに与えています。少し長いですが、以下にソースを載せます。JFrameText.javaだけ別にしてあるのは、なんとなくです。
```ThreadSample2.java
import java.awt.Button;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Semaphore;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

@SuppressWarnings("serial")
public class ThreadSample2 extends JFrame implements ActionListener {
	public static void main(String[] args) {
		ThreadSample2 t=new ThreadSample2();
		t.setSize(500, 360);
		t.setVisible(true);
	}

	static int thMax = 2;
	private final Semaphore semaphore=new Semaphore(thMax,true);
	int maxTime=40;
	public JTextArea ta[];
	JLabel lbl0,lbl1,lbls0,lbls1;
	JPanel p0,ps;
	Button btnRun;

	MyThread th;
	int tasks=6;
	int maxlifeTime=26;

	JFrameText Tframe[];
	int x0=560, y0=0, dy=94;

	ThreadSample2() {
		setTitle("ThreadSample");
		setLayout(new GridLayout(tasks+2,1));
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		lbl0 = new JTimeLabel();
		lbl1 = new JTimePastLabel();
		btnRun=new Button("ThreadRun");
		btnRun.addActionListener(this);
		p0 = new JPanel();
		p0.setLayout(new GridLayout(1,3));
		p0.add(lbl0); 
		p0.add(lbl1);
		p0.add(btnRun);
		add(p0);

		ta = new JTextArea[tasks];
		Tframe = new JFrameText[tasks];
		for(int i=0; i<tasks;i++) {
			Tframe[i] =new JFrameText("frame"+Integer.toString(i), "");
			Tframe[i].setBounds(x0, y0, 240, 100);
			Tframe[i].setVisible(true);
			y0 += dy;
		}

		for(int i=0;i<tasks;i++) {
			ta[i]=new JTextArea("Thread");
			JScrollPane scrollpane = new JScrollPane(ta[i]);
			add(scrollpane);
		}

		lbls0= new JLabel("");
		lbls1= new JLabel("");
		ps= new JPanel();
		ps.setLayout(new GridLayout(1,3));
		ps.add(lbls0);
		ps.add(lbls1);
		add(ps);
	}

	Timer pt;
	class JTimeLabel extends JLabel	{
		private DateFormat fmt;
		Calendar pCal;
		JTimeLabel() {
			setFont(new Font("Consolas",Font.BOLD,24));
			setHorizontalAlignment(CENTER);
			fmt = new SimpleDateFormat("HH:mm:ss");
			pt = new Timer();
			pt.schedule(new TimerLabelTask(), 0, 1000);
		}

		private class TimerLabelTask extends TimerTask {
			public void run() {
				setTime();
			}
		}

		private void setTime() {
			pCal=Calendar.getInstance(Locale.JAPAN);
			setText(fmt.format(pCal.getTime()));
		}
	}

	static long pTime=0;
	Timer t;
	class JTimePastLabel extends JLabel	{
		JTimePastLabel() {
			t = new Timer();
			t.schedule(new TimerLabelTask(), 0, 1000);
		}

		private class TimerLabelTask extends TimerTask {
			public void run() {
				setTime(pTime);
				pTime++;
				if(pTime > maxTime) { 
					ThreadSample2.MyThread.yield();
					pt.cancel();
					t.cancel();}
			}
		}

		private void setTime(long pTime) {
			long t=pTime;
			this.setText("From Start : "+String.valueOf(t));
			if(t % 2 == 0) this.setBackground(Color.white);
			else    	   this.setBackground(Color.cyan);
		}
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		pTime=0;
		lbl1.setText("0");
		lbl1.setVisible(true);
		for(int i=0;i<tasks;i++) {
			Random random = new Random();
			int time=random.nextInt(maxlifeTime)+4;
			th = new MyThread(semaphore,ta[i],Tframe[i],1000,time);
			ta[i].setText(Integer.toString((int) th.getId())+":");
			Tframe[i].ta.setText(Integer.toString((int) th.getId())+":");
			Tframe[i].lb0.setText(th.getName());
			th.start();
		}
	}

	public class MyThread extends Thread {
		final Semaphore semaphore;
		JTextArea jta;
		JFrameText fta;
		int countUpInterval;
		private int execTime;
		private long sTime=0;
		
		MyThread(Semaphore semaphore,JTextArea Ota,JFrameText Fta,int countUpInterval,int execTimeSec) {
			this.semaphore = semaphore;
			jta=Ota;
			fta=Fta;
			this.countUpInterval = countUpInterval;
			this.execTime  = execTimeSec;
			jta.setFont(new Font("Consolas",Font.BOLD,18));
			jta.getCaret().setVisible(true);
		}

		public void run() {
			String str;
			try {
				semaphore.acquire();										
				lbls0.setText(semaphore.getQueueLength()+" acuire");
				jta.setBackground(Color.pink);
				fta.ta.setBackground(Color.pink);
				fta.setVisible(true);
				fta.lb2.setText("Life = " + Integer.toString(execTime));
				for(int i=0;i<pTime;i++) {
					jta.append(".");
					fta.ta.append(".");
					jta.setCaretPosition(jta.getText().length());
					fta.ta.setCaretPosition(fta.ta.getText().length());
				}
				if(pTime != 0) {
					str=jta.getText();
					str=str.substring(0, str.length()-String.valueOf(pTime).length());
					jta.setText(str);
					jta.append(String.valueOf(pTime));
					fta.ta.setText(str);
					fta.ta.append(String.valueOf(pTime));
				}
				sTime=pTime;
				fta.lb1.setText("Start At " + Integer.toString((int) sTime));
				if(sTime+execTime > maxTime) maxTime=(int) (sTime+execTime);
				for(int i=0; i<execTime; i++) {
					jta.append("+");
					fta.ta.append("+");
					jta.setCaretPosition(jta.getText().length());
					fta.ta.setCaretPosition(fta.ta.getText().length());
					try {
						Thread.sleep(countUpInterval);							
					} catch(InterruptedException e) {
						e.printStackTrace();
					}
				}
				str=jta.getText();
				str=str.substring(0, str.length()-String.valueOf(sTime+execTime).length());
				jta.setText(str);
				jta.append(String.valueOf(sTime+execTime));
				fta.ta.setText(str);
				fta.ta.append(String.valueOf(sTime+execTime));
				semaphore.release();										
				lbls1.setText("semaphhore available "+Integer.toString(semaphore.availablePermits()));
				jta.setBackground(Color.green);
				fta.ta.setBackground(Color.green);
			} catch(InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}
```
```JFrameText.java
import java.awt.Font;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

@SuppressWarnings("serial")
public class JFrameText extends JFrame {
	JPanel GP, p0;
	JLabel lb0, lb1, lb2;
	JTextArea ta;
	JScrollPane scp1;
	public JFrameText(String title, String text) {
		super(title);
		GP= new JPanel();
		GP.setLayout(new GridLayout(2,1));

		lb0 = new JLabel("");//	lb0.setBorder(new LineBorder(Color.red,2));
		lb1 = new JLabel("");//	lb1.setBorder(new LineBorder(Color.yellow,2));
		lb2 = new JLabel("");//	lb2.setBorder(new LineBorder(Color.pink,2));
		p0 =new JPanel();
		GridLayout p0layout = new GridLayout(1,3);
		p0.setLayout(p0layout);
		p0.add(lb0);p0.add(lb1);p0.add(lb2);
		GP.add(p0);
		
		ta=new JTextArea(text);
		ta.setFont(new Font("Consolas",Font.BOLD,10));

		scp1 =new JScrollPane(ta);
		GP.add(scp1);
		add(GP);
		setVisible(true);
	}
}
```
一応動くのでそれらしい事をしているのでしょうか💦